More Vicare’s expander development for the internal representation of r6rs record types (see On records). All the changes discussed here are in the master branch.
As experimental (and still undocumented) feature, I have started support for methods
in the definitions of r6rs record types. Three new keyword syntactic bindings
are now exported by the library (vicare)
: method
,
case-method
and method-call
.
The clause method
can be put multiple times in the body of a
define-record-type
use, to define a method for the record–type:
(define-record-type duo (fields one two) (method (sum-them self) (+ (duo-one self) (duo-two self))) (method (mul-them self) (* (duo-one self) (duo-two self))) (method (display self port) (display self port)))
we can think of method
as acting like define
with regard to the
syntax of arguments to function; the first argument to a method is the record itself.
The syntax method-call
is then used to call a record’s methods:
(define {O duo} (make-duo 3 4)) (method-call sum-them O) ⇒ 7 (method-call mul-them O) ⇒ 12 (method-call display O (current-error-port)) (newline (current-error-port)) -| #[record duo one=3 two=4]
The clause case-method
is similar, we can think of it as acting like
case-define
:
(define-record-type alpha (fields a) (case-method on-a ((self) (alpha-a self)) ((self new-val) (alpha-a-set! self new-val)))) (define {O alpha} (make-alpha 1)) (method-call on-a O) ⇒ 1 (method-call on-a O 2) (method-call on-a O) ⇒ 2
The syntax method-call
searches for a record–type’s methods by comparing
the symbols with eq?
(not the syntactic identifiers with
free-identifier=?
).
If a method with the given name is not found: the syntax searches for a field with
the given name, but only if the number of arguments is right. The syntax of
method-call
is:
(method-call ?name ?subject-expr ?arg ...)
(?accessor ?subject-expr)
(?mutator ?subject-expr ?arg)
The clauses method
and case-method
are accepted by
define-record-type
only when the language is non–strict r6rs. The
syntax method-call
is able to retrieve the type of its second argument only
when the tagged language is enabled (at present, only with a few expressions given
that the tagged language is only half–written).
Some time ago I reconsidered dot notation to call a type’s methods (see Reconsidering dot quoting). I do not know the language Clojure, but I read stuff through Reddit; recently a post made me skim through the syntax table of this language and I found that they use the dot notation I have in mind to call Java methods (see Clojure — java_interop1): I am not completely crazy!
Encouraged by this, I have implemented the reader syntax transformation:
(.?symbol ?arg ...) → (method-call ?symbol ?arg ...)
that is, when the reader’s textual input port is configured in ‘#!vicare’ mode:
if a list starts with a symbol; the name of the symbol is a string of length at least
2; the first character of the string is a dot; the second character of the
string is not a dot, then a method-call
symbol is inserted and the
symbol stripped of the dot.
We can try it at the repl:
vicare> '(.ciao) $1 = (method-call ciao)
Notice that r6rs forbids symbols starting with a dot, with the exception of the ellipsis; so everything that was possible before, with the reader, is still possible now.
So we can use this syntax to call a record’s methods as in the following program:
#!vicare (program (demo) (options tagged-language) (import (vicare)) (define-record-type duo (fields one two) (method (sum-them O) (+ (duo-one O) (duo-two O))) (method (mul-them O) (* (duo-one O) (duo-two O))) (method (display O port) (display O port))) (define {O duo} (make-duo 3 4)) (pretty-print (.sum-them O) (current-error-port)) (pretty-print (.mul-them O) (current-error-port)) (.display O (current-error-port)) (newline (current-error-port)) #| end of program |# )
which compiled and run will print:
$ vicare --compile-program demo.sps --output demo $ vicare --binary-program ./demo 7 12 #[record duo one=3 two=4]
This dot notation still looks weird to my eyes, will I get used to it?
This feature of the reader is still undocumented: it is experimental.
By the way: Clojure has some very weird syntax, weirder than the ones I have imagined!