Hi Mark,

Am Fr., 23. Nov. 2018 um 08:56 Uhr schrieb Mark H Weaver <m...@netris.org>:

> Hi Marc,
>
> Marc Nieper-Wißkirchen <m...@nieper-wisskirchen.de> writes:
>
> > Am Mi., 21. Nov. 2018 um 04:38 Uhr schrieb Mark H Weaver <m...@netris.org
> >:
> >
> >  >  Ellipsis identifiers are a bit more tricky, because unlike other
> >  >  bindings, the user-visible ellipsis identifiers are not actually
> >  >  substituted.  We can't do that because ellipsis identifiers can be
> used
> >  >  for other purposes, e.g. bound to ordinary variables or macros, and
> >  >  these two ways of binding ellipsis identifiers should not shadow each
> >  >  other.
>
> Sorry, this was a weak argument.  I've since remembered the _actual_
> reason that it needs to be done this way:
>
> In general, for any sensible binding form, bindings with different names
> should not shadow each other.  For example, a binding for 'E' should not
> shadow a binding for 'F'.
>
> If you try to model (with-ellipsis E BODY) as binding 'E', then it is
> not a sensible binding form in this sense.  Unlike any sensible binding
> form, (with-ellipsis E BODY) should not only shadow outer bindings of
> 'E', but *any* outer ellipsis binding, whether '...' or 'F' or something
> else.  In other words, in this model, there can be only one binding of
> this kind in a given lexical context.
>

Alternatively, it would be enough for all use cases that come to my mind if
`(with-ellipsis E BODY)' besides binding `E' would shadow `...' and nothing
else. E.g. under this alternative semantics, in the BODY of `(with-ellipsis
E (with-ellipsis F BODY))' both `E' and `F' would function as ellipses,
while `...' would not. In other case, `with-ellipsis' would work like the
following macro transformer:

(lambda (stx)
  (syntax-case stx ()
    ((k e body)
     (with-syntax ((::: (datum->syntax k '...)))
       #'(let-syntax ((::: <undefined>) (e <ellipsis>))
           body)))))

This way, `with-ellipsis' would behave more like an ordinary (albeit
unhygienic) binding construct.

Therefore, I think this is a bad model for 'with-ellipsis'.
>
> I think it makes more sense to model (with-ellipsis E BODY) as
> introducing a new lexical binding with a fixed name.  CURRENT-ELLIPSIS
> would be a good name if we wanted to make it part of the public API.  In
> this model, 'E' becomes the _value_ of the binding, instead of the
> binding's name.
>
> Does that make sense?
>

So CURRENT-ELLIPSIS would be the name of an identifier whose name is
disjoint to all names a user could use for their identifiers? Or would you
model CURRENT-ELLIPSIS as a parameter object, which would entail a
different semantics?


> Note that in this later model, it's not natural for (with-ellipsis E
> BODY) to shadow a binding for 'E' or vice versa, because 'E' is not
> actually the thing being bound by 'with-ellipsis'.
>
> In theory, we could introduce additional mechanisms to force
> (with-ellipsis E BODY) to shadow bindings for 'E' and vice versa.  This
> would entail changing *every* binding form to check if the identifier
> being bound matches the current binding of CURRENT-ELLIPSIS, and if so,
> somehow invalidating the ellipsis binding.  It's not obvious what should
> be done in this case.
>
> We could do something like this, but in my view, it would be an ad-hoc
> addition to the semantics in order to support the inadequate mental
> model where (with-ellipsis E BODY) is thought of as binding 'E'.
>
> What do you think?
>

I agree with you that trying to shadow bindings for `E' in a model in which
`with-ellipsis' does not actually bind `E' but some other identifier is the
opposite of being beautiful. So I don't think one should try to do this in
this model.

We have, however, the semantics of R[67]RS, where `...' has an actual
binding as auxiliary syntax. This allows to have more than one identifier
acting as the ellipsis at the same time (just import `...' from `(scheme
base)' or `(rnrs base)' under two different names). Whatever model for
`with-ellipsis' is chosen, it should work well with `R[67]RS'.

It just comes to my mind that this rules out my model from above (the
syntax transformer that rebinds `...'). :-)

So, here may be a better model: Each lexical scope has a flag
ORIGINAL-ELLIPSIS?. In the top-level scope, the flag is set. As long as the
flag is set, `syntax-case' and `syntax' check for the ellipsis by using
`free-identifier=?' and comparing with the binding for `...' as exported by
`(rnrs base)'. Now, `(with-syntax e BODY)' clears this flag in BODY and
binds `e' to a special ellipsis value.

Alternatively, in the model where `with-ellipsis' should not bind anything,
`ORIGINAL-ELLIPSIS?' becomes your `CURRENT-ELLIPSIS'. As long as it is
unset, `syntax-case' and `syntax' check for the ellipsis by using
`free-identifier=?' as above. When `CURRENT-ELLIPSIS' is bound to `e', the
checking is done with `(bound-identifier=? e ---)'.

-- Marc

Reply via email to