In a previous entry (see Musings on the tagged language (part 2) (2015 February 14 bis)) I discussed an idea to solve the problem of having Lispy syntax in the tagged language, without the burden of exporting and importing from libraries a big number of identifiers bound to class methods and field accessors.
In the expression:
(length "ciao")
the literal expression "ciao"
is considered of type <string>
and the
symbol length
, that comes before it, is searched in the list of multimethods
whose first argument is of type <string>
. The class <string>
contains a
table of multimethods whose first argument is of type <string>
. There is no
need to import a binding named length
to access the table of multimethods: if
it is determined at expand–time that an expression returns a value of type
<string>
, the expander has access to the table.
What is the difference between having a table of multimethods in a class and just having a global namespace of multimethod names that is queried before the bindings in the local lexical context? In the program:
(import (vicare)) (length "ciao")
the expander just visits the global namespace first, in search of a method named
length
having one argument with type <string>
:
A global namespace of multimethods is equivalent to multimethods in the class definition.
Is it fine to access it transparently? Or would this transparent access make the code too difficult to interpret for humans? Should a (possibly optional) namespace qualifier be introduced? Possible alternatives:
(.length "ciao") (.append "ciao" " mamma")
the dot is a small and one–keyboard–tap character.
(:: length "ciao") (:: append "ciao" " mamma")
Foreign example: Guile uses the @
character to access bindings from modules
without importing such modules in the lexical context.
(length :: "ciao") (append :: "ciao" " mamma")
(length . "ciao") (append . "ciao" " mamma")
:(length "ciao") :(append "ciao" " mamma")
the reader converts the input:
:(?form0 ?form ...)
into:
(colon ?form0 ?form ...)
where colon
must be an identifier bound in the lexical context of the
expression.
It is currently unused by Vicare. The Scheme reader could be instructed (in
#!vicare
mode) to convert the input:
(append . "ciao" " mamma")
to some special form, like it already does for the apostrophe and similar operators:
the input '(1 2 3)
is read as (quote (1 2 3))
. So, in general:
(?form0 ?form1 ... . ?form2 ?form3 ...)
could be read as:
(improper (?form0 ?form1 ...) (?form2 ?form3 ...))
where improper
must be an identifier bound in the lexical context of the
expression.
But what about:
'(1 2 . 3)
which is a perfectly valid literal expression? The reader should distinguish between quoted and unquoted input: this should not be a reader’s responsibility.
Having a global namespace for multimethod names seems the most sensible solution.
The cleanest way to query this namespace seems to be a proper syntax use like:
(method-call ?name ?operand ...)
where method-call
is defined in the boot image and exported by
(vicare)
. Some reader syntax should be used to obtain a method-call
syntax use from some easy–to–type sequence of characters.