Email list hosting service & mailing list manager

Re: SRFI-212: aliasing to a *not yet* bound identifier, and modules/libraries. Marc Nieper-Wißkirchen (25 Oct 2020 08:10 UTC)

Re: SRFI-212: aliasing to a *not yet* bound identifier, and modules/libraries. Marc Nieper-Wißkirchen 25 Oct 2020 08:09 UTC

Am So., 25. Okt. 2020 um 01:20 Uhr schrieb Jeronimo Pellegrini
<xxxxxx@aleph0.info>:

> >> I was hoping to use aliases in a proposal for a rewrite of STklos'
> >> macro system, and I'd like to know what would be the expected behavior
> >> when I make an alias to an identifier that is not yet bound. Both Chez

You may want to check whether you can use my Unsyntax expander as a
frontend for STklos. It implements the R7RS library and macro system
together with many syntactic extensions, including all macro systems
of SRFI 211.

> > At the moment, SRFI 212 says that the identifier that receives the
> > binding will be unbound as well.
>
> Ok, that clarifies it!

To make SRFI 212 more applicable to existing implementations (like
Chez's), I could make this optional. So an implementation would be
free to reject aliasing an unbound identifier.

> > This is a test of Chez's REPL, whose semantics differ from those of a
> > top-level program. If this were part of a top-level program, you
> > wouldn't be able to "set!" an unbound identifier. (Moreover, Chez
> > doesn't allow to alias an unbound identifier there.)
>
> Sure, but I could define one. And in that case, one would be a
> new binding, so Chez will not answer 10. But Kawa will.
> So this seems like an area where compatibility is not to be
> expected anyway.

In an implementation where all variables are conceptually bound in a
REPL, a subsequent "define" is just a "set!", which seems to be the
reason for Kawa's behavior here. Unsyntax has the same behavior.

Anyway, neither R6RS nor R7RS specify the semantics of the REPL so
that one can write programs that behave the same under any REPL. For
portability, one should restrict oneself to top-level programs.

> >> Would it be a good idea to add this to the spec, or could it perhaps
> >> be a problem?
> >>
> >> For example,
> >>
> >> (let ((a 10))
> >>   (alias x b)
> >>   (let ((b 20))
> >>     x))          ;; error! x is an alias to global b
> >
> > This would be no error if a global "b" was bound.
>
> Yes, I meant when b is not bound.
>
> >> However -- if between the second and third line on that code, for
> >> example, a thread sets a binding for global b, then I would expect
> >> that the code would return the new value of b, since x *is* a binding
> >> to "whatever binding b has at the moment in the global environment".
> >> Or is it not the idea?
> >
> > The binding of "b" at the point where the "alias" definition occurs
> > counts. So if "b" is unbound there, "x" will be unbound there as well.
> >
> > Note that "alias" does not make "x" and "b" equivalent. It just copies
> > the (lexical) binding at that point.
>
> Right, that is clear now.

If you want the other behavior, namely making the identifier "x" and
"b" more or less equivalent, you can use a macro:

(define-syntax x (identifier-syntax b))

This works for all those cases where "x" is macro-expanded. If you,
say, rebind "x" with a let, "x" won't be macro expanded. To make "b"
and "x" absolutely equivalent, you have to wrap everything in a macro:

(let ((a 10))
  (let-syntax
      ((wrapper
        (syntax-rules ()
          ((wrapper b x)
           (let ((b 20))
             x)))))
    (wrapper b b)))

> >> Also, I suppose that if (alias x b) is done inside a module or library,
> >> and the alias is not to a locally created identifier, the binding should
> >
> > Can you give an example? I think I understand but I am not 100% sure.
>
> (in-module acme) ;; set the current module
>
> (define a -1)
>
> (let ((b -2))
>   (alias c a)  ;; this refers to the symbol a in module "acme", and not
>                ;; anywhere else!
>
>
>
> The same for libraries,
>
> (define-library (acme)
>   (export c)
>   (begin
>     (define a -1)
>     ...
>     (alias c a) ;; this refers to a in acme
>   ))
>
> If I import acme and then refer to c, I should get whatever a is bound
> to inside acme. Right?

Yes, this is the correct behavior. The above is effectively the same
as if the export clause were (export (rename a c)).

> >> refer to "b in that module/library" -- is that the intended behavior?
> >> Then, could it be made explicit in the SRFI text?
> >
> > I can speak explicitly of "lexical bindings" in SRFI 212 if this
> > helps.
>
> I believe it would make it more clear, yes!

Great; this wording will appear in the next draft!

Marc