diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/ref/guile.texi | 2 | ||||
-rw-r--r-- | doc/ref/guile/util-object.texi | 86 | ||||
-rw-r--r-- | doc/ref/guile/util-type.texi | 63 | ||||
-rw-r--r-- | doc/ref/guile/util.texi | 21 |
4 files changed, 172 insertions, 0 deletions
diff --git a/doc/ref/guile.texi b/doc/ref/guile.texi index a6c5ebe4..58c162e1 100644 --- a/doc/ref/guile.texi +++ b/doc/ref/guile.texi @@ -7,6 +7,8 @@ @include guile/util.texi @include guile/util-path.texi @include guile/util-config.texi +@include guile/util-type.texi +@include guile/util-object.texi @include guile/base64.texi @include guile/web.texi @include guile/vcomponent.texi diff --git a/doc/ref/guile/util-object.texi b/doc/ref/guile/util-object.texi new file mode 100644 index 00000000..ceac2f2a --- /dev/null +++ b/doc/ref/guile/util-object.texi @@ -0,0 +1,86 @@ +@node define-type +@section Yet Another Object System + +@defmac define-type (name type-parameters ...) fields ... +Introduce a new type. + +Each field is either a symbol, or a list where the first element is a +symbol, and the remaining elements are alternating keywords and +values, as per @ref{Field Parameters}. All fields are optional by +default, but can be made non-optional through its type parameter. + +The example below creates a new type called @var{type}, with a custom +printer which always displays the string ``TYPE''. It has two fields, +@var{x}, which must be an integer, and @var{y}, which can have any +type, but gets the value ``Hello'' in none is given. +@example +(define-type (type #:printer (lambda (r p) (display "TYPE" p))) + (x #:type integer?) + (y #:default "Hello")) +@end example +@end defmac + +@subsection Type Parameters + +@deffn {Type Parameter} constructor (λ (primitive-constructor type-validator)) +Use a custom constructor for the type. The given procedure is called +with two values: +@itemize +@item the types primitive (and usually hidden) constructor, +which takes as many arguments as there are fields, in the order given +in define-type, and +@item the type validator procedure, which also takes all arguments, +but instead either returns an undefined value if everything is fine, +or throws @code{'wrong-type-arg} otherwise. +@end itemize +The procedure should then return a new procedure, which will be bound +as the constructor for the type. Note that default values are current +disregarded with custom constructors. + +A custom constructor for the type above might look like +@example +(lambda (primitive-constructor type-check) + (lambda* (#:key x y) + (type-check x y) + (primitive-constructor x y))) +@end example +@end deffn + +@deffn {Type Parameter} printer (λ (record port)) +Use a custom printer for the type. +@end deffn + +@subsection Field Parameters +@anchor{Field Parameters} + +@deffn {Field Parameter} default value +Value the field should get if not given. +@end deffn + +@deffn {Field Parameter} type type-clause +A type predicate that the field must obey. See @ref{type-clause} for details. +@end deffn + +@subsection Introduced Bindings + +Define type introduces a number procedures. (@var{<name>} should be +replaced with whatever was given as @var{name} to define-type. + +@defun @var{<name>} [kv-args ...] +Type constructor. Takes key-value arguments. Where the keys are the +names of the fields. +@end defun + +@defun @var{<name>}? x +Type predicate. +@end defun + +And for each field @var{<field>}: + +@defun @var{<field>} object [value] +Accessor for the given filed. +Returns the current value if called with only an object, and returns a +new object with @var{field} set to @var{value} if called with two values. + +The updating version checks the type if #:type was given on creation. +@end defun diff --git a/doc/ref/guile/util-type.texi b/doc/ref/guile/util-type.texi new file mode 100644 index 00000000..d389287e --- /dev/null +++ b/doc/ref/guile/util-type.texi @@ -0,0 +1,63 @@ +@node Type utilities +@section Type utilities + +Provided by the module @code{(hnh util type)} + +@subsection Type Clauses +@anchor{type-clause} +@cindex type-clause + +Type clauses are an effective way of writing compound predicates +without explicitly mentioning the variable at all steps. + +The simplest type predicate is a single symbol, which is directly +called on the object: +@example +predicate? ⇒ (predicate? x) +@end example + +Otherwise, if the predicate is a list then the variable is spliced +into the argument list in the first position: +@example +(proc args ...) ⇒ (proc x args ...) +@end example + +The primitives @code{and}, @code{or}, and @code{not} are also +available, which each take the same number of predicates as schemes +primitives of the same name, and calls them in order, with Scheme's +usual short-circuiting rules. @footnote{These don't have to be +primitives, but we would otherwise have one hell of a namespace +conflict} + +@defmac list-of variable type-clause +Checks if @var{variable} is a list, and that every element satisfies type-clause. +@end defmac + +@defmac pair-of variable car-type-clause cdr-type-clause +Check if @var{variable} is a cons-pair, and that the car satisfies +@var{car-type-clause}, and that the cdr satisfies @var{cdr-type-clause}. +@end defmac + +@subsection Deffinitions + +@defmac build-validator-body variable type-clause +``Entry point'' of type clauses. Inserts variable into the +type-clause, returning something ready to be passed along the eval (or +rather, spliced into another macro). + +Also used if new ``primitives'' are to be added, such as list-of. +@end defmac + +@defmac typecheck variable type-clause [procedure-name=(current-procedure-name)] +Checks @var{variable} against @var{type-clause}, and raises +@code{'wrong-type-argument} if it fails. @var{procedure-name} is used +as the calling procedure for @code{scm-error}. + +Useful at the start of procedures. +@end defmac + + +@defmac current-procedure-name +Returns the current procedure name as a symbol, or @code{#f} if not found. +@end defmac + diff --git a/doc/ref/guile/util.texi b/doc/ref/guile/util.texi index 32df5fce..222b59c5 100644 --- a/doc/ref/guile/util.texi +++ b/doc/ref/guile/util.texi @@ -198,6 +198,27 @@ Split a list into sub-lists on @var{element} @end lisp @end defun +@defun split-by-one-of lst items +Like split-by, but takes a list of delimiters. +Returns a list where the first element is everything before the first +delimiter, and the remaining elements is the splitting delimiter +consed with everything until the next delimiter. + +@lisp +(split-by-one-of '() '(+))) +⇒ (()) + +(split-by-one-of '(1 + 2) '(/)) +⇒ ((1 + 2)) + +(split-by-one-of '(1 + 2 - 3) '(+ -)) +⇒ ((1) (+ 2) (- 3)) + +(split-by-one-of '(1 + 2 * 3 + 4) '(*)) +⇒ ((1 + 2) (* 3 + 4)) +@end lisp +@end defun + @defun span-upto count predicate list Simar to span from srfi-1, but never takes more than |