Previous: Memoization, Up: Higher Ordered Fun
To make use of idiomatic calling-convention macros, evaluate the form:
(use-modules (ice-9 calling))
Expand to a form that saves the values for each binding named in vars, a list of unevaluated symbols naming bindings in the
save-bindings-excursioncaller, evaluates the body forms, then restores the values. These operations form the three branches of adynamic-wind. Here is an example:(define a 42) (define c 99) (define (chk!) (write-line (list #:a a #:c c))) (save-bindings-excursion (a c) (chk!) (set! a 0) (set! c -1) (chk!))
Expand to an application of collect to an excursion proc ex. ex takes one argument, a thunk, which forms the middle branch of a
dynamic-wind. In the first branch, ex saves the values of vars, a list of unevaluated symbols naming bindings in thewith-excursion-functioncaller. In the third branch, ex restores these values. Here is an example that shows how to use this macro:(with-excursion-function (a c) (lambda (ex) (ex (lambda () (chk!) (set! a 0) (set! c -1) (chk!)))))In this example, collect is an anonymous procedure, and the excursion proc is named
ex. Note that this is functionally equivalent to the one forsave-bindings-excursion(with setup definitions elided).
Expand to an application of collect to getter and setter procs for vars, an unevaluated list of symbols naming bindings in the caller of
with-getter-and-setter. The call looks like:(collect getter setter)getter and setter are procedures used to access or modify vars. setter, called with keywords arguments, modifies the named values. For example, if
fooandbarare among vars, then:(setter #:foo 1 #:bar 2) === (begin (set! foo 1) (set! bar 2))getter, called with just keywords, returns a list of the corresponding values. To continue the above example:
(getter #:foo #:bar) ⇒ (1 2)getter, called with no arguments, returns a list of all accepted keywords and the corresponding values. To continue the above example, with the additional stipulation that
fooandbarare the only names in vars:(getter) ⇒ (#:foo 1 #:bar 2)These calling sequences supports two handy idioms:
(apply setter (getter)) ;; save and restore (apply-to-args (getter #:foo #:bar) ;; fetch and bind (lambda (foo bar) ....))
Expand to an application of collect to getter and setter procs for vars, an unevaluated list of symbols naming bindings in the caller of
with-delegating-getter-and-setter. The call looks like:(collect getter setter)If given a name not in vars, getter and setter call sub-g and sub-s, respectively.
Expand to an application of collect to excursion proc ex, getter and setter procs for vars, an unevaluated list of symbols naming bindings in the caller of
with-excursion-getter-and-setter. The call looks like:(collect excursion getter setter)See
with-excursion-functionandwith-getter-and-setter.
Expand to an application of collect to getter and setter procs for vars-etc, a list of binding specifiers for bindings visible in the caller of
with-configuration-getter-and-setter. The call looks like:(collect getter setter)getter and setter can trigger arbitrary computation, according to the binding specifier, which has the form:
(name [getter-hook [setter-hook]])Both hook elements are evaluated; name is not. Either hook may be #f or a procedure.
getter-hook is a thunk that returns a value for the corresponding name. If omitted (or #f is passed), use the normal value of
name.setter-hook is a procedure of one argument that accepts a new value for name. If omitted, name is simply updated with
set!.
Like
with-delegating-getter-and-setterbut using vars-etc as withwith-configuration-getter-and-setter.
Like
with-configuration-getter-and-setterexcept that each element of vars-etc is:(name initial-value getter-hook setter-hook)Also, this macro introduces an additional lexical binding for each of the names in
vars-etc. It is short-hand for:(let ((<var1> initial-value-1) (<var2> initial-value-2) ...) (with-configuration-getter-and-setter ((<var1> v1-get v1-set) (<var2> v2-get v2-set) ...) collect))