diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-03-06 20:53:48 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-03-06 20:53:48 -0800 |
commit | fd87267eb4802d1e3ec3c22a48e09a86f76810ad (patch) | |
tree | 8760a2fb325d259e5e86983b20f690ee08da93c4 /txr.1 | |
parent | 266e28cb7129d175ad4af5af5cb45fbbd3054862 (diff) | |
download | txr-fd87267eb4802d1e3ec3c22a48e09a86f76810ad.tar.gz txr-fd87267eb4802d1e3ec3c22a48e09a86f76810ad.tar.bz2 txr-fd87267eb4802d1e3ec3c22a48e09a86f76810ad.zip |
uref: the a.b.c syntax extended to .a.b.c
Now it is possible to use a leading dot on the referencing
dot syntax. This is the is the "unbound reference dot". It
expands to the uref macro, which denotes an unbound-reference:
it produces a function which takes an object as the argument,
and curries the reference implied by the remaining arguments.
* eval.c (uref_s): New global symbol variable.
(eval_init): Intern uref symbol and init uref_s.
* eval.h (uref_s): Declared.
* lib.c (simple_qref_args_p): A qref expression is now
also not simple if it contains an embedded uref, meaning
that it cannot be rendered into the dot notation without
ambiguity.
(obj_print_impl): Support printing (uref a b c) as .a.b.c.
* lisplib.c (struct_set_entries): Add uref to the list of
autoload triggers for struct.tl.
* parser.l (DOTDOT): Consume any leading whitespace as part
of recognizing the DOTDOT token. Otherwise the new rule
for UREFDOT, which matches (mandatory) leading space
will take precedence, causing " .." to be scanned wrong.
(UREFDOT): Rule for new kind of dot token, which is
preceded by mandatory whitespace, and isn't consing
dot (which has mandatory trailing whitespace too,
matched by an earlier rule).
* parser.y (UREFDOT): New token type.
(i_dot_expr, n_dot_expr): New grammar rules.
(list): Handle a leading dot on the first element of a list as
a special case. Things are done this way because trying to
work a UREFDOT into the grammar otherwise causes intractable
conflicts.
(i_expr): The ^, ' and , punctuators are now followed by
an i_dot_expr, so that the expression can be an unbound
dot.
(n_expr): Same change as in i_expr, but using n_dot_expr.
Plus new UREFDOT n_expr production.
* share/txr/stdlib/struct.tl (uref): New macro.
* txr.1: Documented.
Diffstat (limited to 'txr.1')
-rw-r--r-- | txr.1 | 142 |
1 files changed, 140 insertions, 2 deletions
@@ -10595,6 +10595,56 @@ Such ambiguous uses of floating-point tokens are diagnosed as syntax errors: (a .4) ;; good: a followed by 0.4 .cble +.NP* Unbound Referencing Dot + +Closely related to the referencing dot syntax is the unbound +referencing dot. This is a dot which is flanked by an expression on the right, +without any intervening whitespace, but is not preceded by an expression +Rather, it is preceded by whitespace, +or some punctuation such as +.codn [ , +.code ( +or +.codn ' . +This is a syntactic sugar which translates to +.code uref +syntax: + +.cblk + .a <--> (uref a) + .a.b <--> (uref a b) +.cble + +When the unbound referencing dot is applied to a dotted expression, +this can be understood as a conversion of +.code qref +to +.codn uref . + +Indeed, this is exactly what happens if the unbound dot is applied to an +explicit +.code qref +expression: + + .(qref a b) <--> (uref a b) + +The unbound referencing dot takes its name from the semantics of the +.code uref +macro, which produces a function that implements late binding of an +object to a method slot. Whereas the expression +.code obj.a.b +denotes accessing object +.code obj +to retrieve slot +.code a +and then accessing slot +.code b +of the object from that slot, the expression +.code .a.b. +represents a "disembodied" reference: it produces a function which takes an +object as an argument and then performs the implied slot referencing on that +argument. When the function is called, it is said to bind the referencing to +the object. Hence that referencing is "unbound". .NP* Quote and Quasiquote @@ -21632,9 +21682,12 @@ For more convenient and clutter-free expression of structure-based program code, macros are also provided. Furthermore, concise and expressive slot access syntax is provided courtesy of -the referencing dot syntax, a syntactic sugar for the +the referencing dot and unbound referencing dot syntax, a syntactic sugar +for the .code qref -macro. +and +.code uref +macros. Structure types have a name, which is a symbol. The .code typeof @@ -22557,6 +22610,91 @@ function which is particular to the object. Secondly, the object is passed to the selected function as the leftmost argument, so that the function has access to the object. +.coNP Macro @ uref +.synb +.mets (uref >> { slot | >> ( slot << arg *) | >> [ slot << arg *]}+) +.syne +.desc +The +.code uref +macro expands to an expression which evaluates to a function. +The function takes exactly one argument: an object. +When the function is invoked on an object, it references slots +or methods relative to that object. + +Note: the +.code uref +syntax may be used directly, but it is also produced by the unbound referencing +dot syntactic sugar: + +.cblk + .a --> (uref a) + .(f x) --> (uref (f x)) + .(f x).b --> (uref (f x) b) + .a.(f x).b --> (uref a (f x) b) +.cble + +The macro may be understood in terms of the following translation +scheme: + +.cblk + (uref a b c ...) --> (lambda (o) (qref o a b c ...)) +.cble + +where +.code o +is understood to be a unique symbol (for instance, as produced by the +.code gensym +function). + +When only one +.code uref +argument is present, these equivalences also hold: + +.cblk + (uref (f a b c ...)) <--> (umeth f a b c ...) + (uref s) <--> (usl s) +.cble + +.TP* Examples: + +Suppose that the objects in +.code list +have slots +.code a +and +.codn b . +Then, a list of the +.code a +slot values may be obtained using: + +.cblk + (mapcar .a list) +.cble + +because this is equivalent to + +.cblk + (mapcar (lambda (o) o.a) list) +.cble + +Because +.code uref +produces a function, its result can be operated upon by +functional combinators. For instance, we can use the +.code juxt +combinator to produce a list of two-element lists, +which hold the +.code a +and +.code b +slots from each object in +.codn list : + +.cblk + (mapcar (juxt .a .b) list) +.cble + .coNP Macro @ meth .synb .mets (meth < struct < slot << curried-expr *) |