From ffd0a028aefd203b4a42ded1e5a592e1b4d92dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Mon, 4 Dec 2023 01:58:26 +0100 Subject: Complete rewrite of the lens system. The old "lens" system was more of nested accessors. This rewrites them to be much better, at the cost of some extra up-front complexity. Beside the change in lenses, and all required adjustments, also adds lens creation to the define-type macro. --- doc/ref/general/lens.texi | 93 ++++++++++++++++++++-------------------------- doc/ref/object/object.texi | 28 ++++++++++---- 2 files changed, 61 insertions(+), 60 deletions(-) (limited to 'doc/ref') diff --git a/doc/ref/general/lens.texi b/doc/ref/general/lens.texi index 144478c3..bdf05a61 100644 --- a/doc/ref/general/lens.texi +++ b/doc/ref/general/lens.texi @@ -3,69 +3,58 @@ Provided by the module @code{(hnh util lens)} -A lens system for Scheme. All these procedures are pure. In general, -procedures fetching values from objects return that value, while -procedures ``setting'' or ``mutating'' objects returns a new instance -of the object, with the field in question replaced. - -Lenses aren't a special type, but rather procedures which return a -value when called with one argument, and produce a new container with -an updated value when called with two arguments. - -For example, the lens to focus the first element of a pair is -implemented as: - -@lisp -(define car* - (case-lambda ((pair) (car pair)) - ((pair value) (cons value (cdr pair))))) -@end lisp - -@defun compose-lenses lenses ... -@defunx lens-compose lenses ... -Creates a new lens, which is the compound from all the given lenses. - -Lenses composes left to right, so earlier lenses in @var{lenses} are -applied earlier. -@end defun +A lens system for Scheme. -@defmac get object lenses ... -Do a deep lookup. Lenses are composed as per @code{compose-lenses}. -@end defmac +@subsection Overview -@defmac set object lenses ... value -Do a deep update of a field, and return a new object with the focused -element replaced. Lenses are composed as per @code{compose-lenses}. -@end defmac +@subsection Using Lenses -@defun modify object lens f args ... +@defun modify container lens f Returns a new object, with the value focused by @var{lens} replaced by the result of calling @var{f}, with the old value, and the extra arguments given. @end defun -@defmac modify* object lens ... f -Like @code{modify}, but auto compose lenses, and don't allow extra -arguments to @var{f}. -@end defmac +@defun set container lens value +Like modify, but sets a fixed value. +@end defun -@defmac build-lens getter setter -Where any of getter or setter can either be a single symbol, or a list. -@end defmac +@defun get container lens +Get the value focused by lens. Only a single value can me focused. +@end defun -@deftp {Scheme Lens} identity-lens -A lens focusing the given object. Showing the value returns the root -value, and setting the value just returns the new value. -@end deftp +@defun traversed container lens +Similar to @code{get}, but returns a list of all focused elements. -@deftp {Scheme Lens} ref idx -Focuses the element at index @var{idx} in a list. -@end deftp +Note that this ``runs'' the lens for each elemement, (where ``modify'' +doesn't). So use with caution. +@end defun -@deftp {Scheme Lens} car* -@deftpx {Scheme Lens} cdr* -Focuses the first or second element of a pair. -@end deftp +@defun lens-compose lenses ... +@defunx compose-lens lenses ... +Creates a new lens, which is the compound from all the given lenses. -@defun each object lens proc +Lenses composes left to right, so earlier lenses in @var{lenses} are +applied earlier. @end defun + +@subsection Built in Lenses + +@deffn {Lens} car* +@deffnx {Lens} cdr* +Focuses the first or second element of a pair. +@end deffn + +@deffn {Lens} ref idx +Focuses the element at index @var{idx} in a list. +@end deffn + +@deffn {Lens} identity-lens +A lens focusing the given object. Showing the value returns the root +value, and setting the value just returns the new value. +@end deffn + +@deffn {Lens} focus-matching predicate +A lens focusing each element of a list where @var{predicate} returns +true. This may be multiple elements. +@end deffn diff --git a/doc/ref/object/object.texi b/doc/ref/object/object.texi index a21ae9ea..f56a8162 100644 --- a/doc/ref/object/object.texi +++ b/doc/ref/object/object.texi @@ -89,6 +89,26 @@ symbol, and @emph{not} a keyword object. @end example @end deffn +@deffn {Field Parameter} #:accessor name +Explicit name for the accessor of this field. Will otherwise use the +fields name. + +Each accessor is a procedure which either +@itemize +@item retrives the field from the record (if one argument was given), or +@item returns a new record with that field replaced (if two arguments +where given). +@end itemize + +@end deffn + +@deffn {Field Parameter} #:lens name +Explicit name for the lens +@c TODO link to lens documentation +focusing this field. Will use the fields +name, with a star (``*'') appended by if unset.. +@end deffn + Each type introduces a number of bindings, which are@footnote{ @var{} here refers to the name of the type }: @@ -104,12 +124,4 @@ Type predicate. And for each field @var{}: -@defun @var{} 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 - @end defmac -- cgit v1.2.3