• Top-level definition of unquote

    From Stefan Monnier@21:1/5 to All on Wed Nov 17 21:27:45 2021
    I've been toying with the idea of defining (in ELisp) `,` as a macro
    which would "naturally" generalize the `,` of the backquote macro to its meaning outside of backquotes:

    (defmacro \, (exp)
    (eval exp))

    Then you have that

    ,`EXP

    is equivalent to

    EXP

    at top-level as well.

    AFAICT this is not done in Common-Lisp, so I'm wondering if there's
    a particular reason why it is so, and whether other Lisps have adopted
    such a thing (or not and why not),


    Stefan

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Alan Bawden@21:1/5 to All on Wed Nov 17 23:09:59 2021
    Stefan Monnier <monnier@iro.umontreal.ca> writes:

    I've been toying with the idea of defining (in ELisp) `,` as a macro
    which would "naturally" generalize the `,` of the backquote macro to its
    meaning outside of backquotes:

    (defmacro \, (exp)
    (eval exp))

    Then you have that

    ,`EXP

    is equivalent to

    EXP

    at top-level as well.

    AFAICT this is not done in Common-Lisp, so I'm wondering if there's
    a particular reason why it is so, and whether other Lisps have adopted
    such a thing (or not and why not),

    Random unconnected thoughts:

    Your simple defmacro above will be evaluating that expression in an
    environment other than the lexical one where the expression appeared.

    Common Lisp has "#." which calls eval at read time.

    Lisp Machine Lisp had "#," which was like "#." but delayed executing the
    form until load time. "#," was removed from Common Lisp because it was difficult for everyone to agree on what that meant exactly.

    Scheme allows you to write ",foo" anywhere and just reads it as
    "(unquote foo)".

    Some dialects of Lisp use a leading "," in the read-eval-print loop to
    be an escape to some form of command language.

    I always thought that it was an advantage in Common Lisp that ","
    outside of a backquote was an error, because it would catch mistakes
    where I missed a backquote somewhere -- similar to checking that my
    parentheses were balanced.

    --
    Alan Bawden

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Alan Bawden on Thu Nov 18 08:06:04 2021
    On 2021-11-18, Alan Bawden <alan@csail.mit.edu> wrote:
    Lisp Machine Lisp had "#," which was like "#." but delayed executing the
    form until load time. "#," was removed from Common Lisp because it was difficult for everyone to agree on what that meant exactly.

    What does that do that isn't covered by load-time-value?

    I suppose interpolation into a context that isn't evaluated,
    like hash-dot:

    (quote (1 2 3 4 #,(+ 2 3))))

    But that means that the entire quote does not make sense as a true
    literal. It is hard to see what that should mean, and by what
    mechanism.

    What that code seems to want is for the whole thing to be a load-time
    literal:

    (load-time-value `(1 2 3 4 ,(+ 2 3)))

    The (+ 2 3) happens at load time, gets inserted into a list, and
    that list then behaves like a literal in the loaded code.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Alan Bawden@21:1/5 to Alan Bawden on Thu Nov 18 09:36:55 2021
    Kaz Kylheku <480-992-1380@kylheku.com> writes:

    On 2021-11-18, Alan Bawden <alan@csail.mit.edu> wrote:
    > Lisp Machine Lisp had "#," which was like "#." but delayed executing the
    > form until load time. "#," was removed from Common Lisp because it was
    > difficult for everyone to agree on what that meant exactly.

    What does that do that isn't covered by load-time-value?

    See below.

    I suppose interpolation into a context that isn't evaluated,
    like hash-dot:

    (quote (1 2 3 4 #,(+ 2 3))))

    I believe "#," was in fact restricted to appear only in constants.

    But that means that the entire quote does not make sense as a true
    literal. It is hard to see what that should mean, and by what
    mechanism.

    As I recall, it required some support from the way constants were
    represented in compiled files.

    As I said, "it was difficult for everyone to agree on what that meant
    exactly". I believe LOAD-TIME-VALUE was added as a replacement
    precisely because people _could_ agree on what it meant.

    --
    Alan Bawden

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Monnier@21:1/5 to All on Thu Nov 18 15:31:30 2021
    Alan Bawden [2021-11-17 23:09:59] wrote:
    Stefan Monnier <monnier@iro.umontreal.ca> writes:

    I've been toying with the idea of defining (in ELisp) `,` as a macro
    which would "naturally" generalize the `,` of the backquote macro to its
    meaning outside of backquotes:

    (defmacro \, (exp)
    (eval exp))

    Then you have that

    ,`EXP

    is equivalent to

    EXP

    at top-level as well.

    AFAICT this is not done in Common-Lisp, so I'm wondering if there's
    a particular reason why it is so, and whether other Lisps have adopted
    such a thing (or not and why not),

    Random unconnected thoughts:

    Your simple defmacro above will be evaluating that expression in an environment other than the lexical one where the expression appeared.

    Depends what you mean by "the lexical one where the expression appeared".
    E.g. in:

    `(let ((x 2)) ,(+ x 5))

    do you consider the `(x 2)` binding as part of the lexical environment
    where `(+ x 5)` appears? [ I hope not. ]

    Common Lisp has "#." which calls eval at read time.

    Lisp Machine Lisp had "#," which was like "#." but delayed executing the
    form until load time. "#," was removed from Common Lisp because it was difficult for everyone to agree on what that meant exactly.

    Hmm... these are quite different: the purpose of the above `,` is to be
    able to build *code* at compile-time.

    Scheme allows you to write ",foo" anywhere and just reads it as
    "(unquote foo)".

    Same in ELisp: if you write ,foo it'll be read as (\, foo).
    The question is whether `unquote` or `,` is globally defined as
    a function macro or not.

    I always thought that it was an advantage in Common Lisp that ","
    outside of a backquote was an error, because it would catch mistakes
    where I missed a backquote somewhere -- similar to checking that my parentheses were balanced.

    Of course, that's the usual tradeoff.

    BTW, one downside of the above `,` macro is that it will inevitably make programmers want to have a matching `,@` top-level functionality, but
    that can't be defined as cleanly/simply with a macro.


    Stefan

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Alan Bawden@21:1/5 to monnier@iro.umontreal.ca on Fri Nov 19 01:25:45 2021
    Stefan Monnier <monnier@iro.umontreal.ca> writes:

    Alan Bawden [2021-11-17 23:09:59] wrote:
    > Random unconnected thoughts:
    >
    > Your simple defmacro above will be evaluating that expression in an
    > environment other than the lexical one where the expression appeared.

    Depends what you mean by "the lexical one where the expression appeared".
    E.g. in:

    `(let ((x 2)) ,(+ x 5))

    do you consider the `(x 2)` binding as part of the lexical environment
    where `(+ x 5)` appears? [ I hope not. ]

    In your example, The lexical environment where "(+ x 5)" appears is, of
    course, the environment that surrounds the backquote expression -- which presumably has a binding for "x". The "x" in "((x 2))" is just a
    symbol.

    But you are proposing that a naked ",(+ x 5)" will be evaluated in an environment that does _not_ lexically surround the site where it
    occurred. It's an environment that will be _gone_ before any
    environment that can be said to surround the comma expression even comes
    into existance, because you'll be calling EVAL at macro-expand-time
    (which is usually compile-time), and _that_ environment will be dead and
    gone before the resulting code is run. That "x", if it refers to
    anything at all, refers to a binding that is in no way lexically
    apparent at the site of the comma expression.

    At least that's the way I understand the word "lexical". That's the way
    I was using it when I wrote "the lexical [environment] where the
    expression appeared".

    > Common Lisp has "#." which calls eval at read time.
    >
    > Lisp Machine Lisp had "#," which was like "#." but delayed executing the
    > form until load time. "#," was removed from Common Lisp because it was
    > difficult for everyone to agree on what that meant exactly.

    Hmm... these are quite different: the purpose of the above `,` is to be
    able to build *code* at compile-time.

    They seem pretty similar to me, actually. I can use "#." to build code
    as well as data. Read-time and compile-time are pretty close to each
    other in practice.

    --
    Alan Bawden

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Monnier@21:1/5 to All on Fri Nov 19 13:53:58 2021
    But you are proposing that a naked ",(+ x 5)" will be evaluated in an environment that does _not_ lexically surround the site where it
    occurred.

    ELisp's definition of which environment is used in such circumstances is
    indeed problematic/nonexisting, but if I were to adapt this to something
    like the Common Lisp spec, it would make sense to define it as running
    in the same surrounding lexical environment as the surrounding lexical environment that would apply for the body of a `defmacro` or an
    `eval-when`, and you'd probably restrict it to be used at top-level.

    All the current uses of this kind of `,` macro in ELisp are at top-level.

    Basically,

    ,EXP

    is used as a shorthand for

    (defmacro XX () EXP)
    (XX)

    > Common Lisp has "#." which calls eval at read time.
    >
    > Lisp Machine Lisp had "#," which was like "#." but delayed executing the
    > form until load time. "#," was removed from Common Lisp because it was
    > difficult for everyone to agree on what that meant exactly.

    Hmm... these are quite different: the purpose of the above `,` is to be
    able to build *code* at compile-time.

    They seem pretty similar to me, actually. I can use "#." to build code
    as well as data. Read-time and compile-time are pretty close to each
    other in practice.

    Oh, indeed, thanks.


    Stefan

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)