[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: lists in enclosed expression



On 05/13/2013 03:59 PM, John Cowan wrote:
Per Bothner scripsit:

Specially, do you like it:
- as a special syntax for SRFI-10[789] should define for enclosed
expression?

This.

It is?  I see '@' listed as a <special subsequent> but not a
<special initial>.

The devil is in the details, but I think I've worked out
(most of) the details.  This is somewhat long-winded ...

First, the reader parses @FORM as ($splice$ FORM).  In the Kawa
prototype, this is done pervasively.  (More on this later.)
Alternatively, a SRFI-10[789] implementation may special-case
the syntax of enclosed-part:

enclosed-part ::=
    "&" enclosed-modifier "[" enclosed-expression*  "]"
  | "&" enclosed-modifier "(" expression+ ")"

enclosed-expression ::= expression | "@" expression

For Kawa I'm considering allowing '"@" expression' in general
application context.  Thus:
  (fexp @aexp)
would be equivalent to:
  (apply fexp aexp)
except aexp can be a list *or* a vector.  Also, '@EXP' would only be
allowed in application context - it is syntax, not expression.
(Otherwise type-checking/-inference, code optimization, and
readability are hurt too much, IMO.)

For example the list function partially subsumes list, cons, append,
and variants:
  (list x @y) === (cons x (list-copy y))
  (list @a @b @c) === (append a b (list-copy c))

Of course the above is not part any of the current SRFIs;
it's just motivation of why generalizing @ makes sense.

Another issue is the interaction with format specifiers.
These are not part of these SRFIs, but they are in the Kawa
prototype, and may be in a followup SRFI, so we want to
be confident $splice$ and format work together.  What
makes it non-trivial is that format specifiers are
optional, *and* that we want to allow the more complex
Common Lisp format specifiers which are not in one-to-one
correspondence with the argument values.

Luckily, a simple solution appears sane and to work well:
If no format specifier is given, an implicit specifier of
"~a" is added for *each* sub-expression.  Thus:
  &[exp1 exp2 exp3]
is equivalent to:
  ~a[exp1]~a[exp2]~a[exp3]
Similarly:
  &[@exp]
is equivalent to:
  &~{~a~}[exp]
I.e. "~{~a~}" is added to the format string.
(Kawa allows multiple format specifiers before an
enclosed expressions.)

This handles what happens when producing a string.
as in SRFI-109, or the 2-argument version of SRFI-108's
define-simple-constructor.  In general, the reader-produced
forms contain $splice$ forms - as do the init-args when using
define-simple-constructor.

Should define-simple-constructor handle "de-sugaring" $splice$
forms?  If so how?  The issue is whether to *allow* the user-provided
cname-maker and str-maker macros/functions to handle $splice$,
or to *require* them to.  In the latter case, no problem to
us Scheme implementors, but it complicates $construct$:foo
implementations.  If we allow tcname-maker/str-maker to handle
the desugaring, without requiring them to, then we need a
post-processor phase to re-write the resulting form to an apply call,
which is tricky and not always appropriate.

This is not a problem for an implementation where ($splice$ args)
is handled pervasively by the implicit apply done on each function
call.  In that case it gets handled automatically.

I'm leaning towards deferring the issue to a separate SRFI
to handle $splice$ more generally.

A possible compromise is partial solution/specification:
(1) Define the reader to map @FORM to ($splice FORM),
at least within an enclosed-part (i.e. inside &[...]).
(2) Specify that ($string$ ...) handle $splice, by
appending the result.
(3) Also SRFI-107 (XML constructor) forms should handle $splice$.
(4) Leave it up to the implementation of each $construst$:foo
to handle $splice$, except on implementations handle it pervasively.

The final issue I'm dealing with is the Kawa-specific one where @foo
conflicts with Java-style annotations.  However, this ambiguity isn't
really a problem in practice because of 3 "disambiguators":
(1) When @foo is a splice then foo has to be list/vector value.  For
annotations, foo has to be an annotation class.
(2) Annotations are only used in function call position:
  (@XmlAttribute required: #t)
Splices are used for function arguments:
  (func ... @splice ...)
I guess in theory one could allow a compound function-call splice:
  (define call (list func arg1 arg2 arg3))
  (@call)  ;; equivalent to (func arg1 arg2 arg3)
However, that doesn't seem terribly useful.
(3) Annotations are always (almost always?) used in declaration
forms (e.g. class declarations), in specific syntactic contexts.

(The above is probably Too Much Information except for people
who care about Kawa.)
--
	--Per Bothner
per@xxxxxxxxxxx   http://per.bothner.com/