unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* Making apostrophe, backtick, etc. hygienic?
@ 2015-08-30 12:30 Taylan Ulrich Bayırlı/Kammer
  2015-08-30 12:48 ` Panicz Maciej Godek
  2015-09-02  2:55 ` Mark H Weaver
  0 siblings, 2 replies; 8+ messages in thread
From: Taylan Ulrich Bayırlı/Kammer @ 2015-08-30 12:30 UTC (permalink / raw)
  To: guile-devel

This is a bit of a crank idea, but here goes.

Today I wasted some time trying to find the bug in the following piece
of code:

    (define (syntax-car syntax)
      (syntax-case syntax () ((car . cdr) #'car)))

Better error reporting in macro-expansion errors might have made it less
painful, but maybe we can solve the problem itself.

How about making 'foo turn into something like (__quote__ foo), and
similar for `foo, #'foo, etc.?  Where __quote__ is just a synonym to
quote, and the original works too.  Ideal would be a symbol that's not
as noisy (in debug output) but still highly improbable to appear in user
code and be accidentally shadowed.

Maybe it would not be standards-compliant in the strict sense, but I
believe it would be an improvement.

Am I missing any obvious downsides?  Or any subtle ones?

I peeked into Guile's sources to see where one might start implementing
this (read.c, expand.c, psyntax.scm?) but better to ask for some input
since it might be a controversial change, and I'm still a total noob in
Guile's code-base.

Taylan



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Making apostrophe, backtick, etc. hygienic?
  2015-08-30 12:30 Making apostrophe, backtick, etc. hygienic? Taylan Ulrich Bayırlı/Kammer
@ 2015-08-30 12:48 ` Panicz Maciej Godek
  2015-08-30 13:16   ` Taylan Ulrich Bayırlı/Kammer
  2015-09-02  2:55 ` Mark H Weaver
  1 sibling, 1 reply; 8+ messages in thread
From: Panicz Maciej Godek @ 2015-08-30 12:48 UTC (permalink / raw)
  To: Taylan Ulrich Bayırlı/Kammer; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 1642 bytes --]

2015-08-30 14:30 GMT+02:00 Taylan Ulrich Bayırlı/Kammer <
taylanbayirli@gmail.com>:

> This is a bit of a crank idea, but here goes.
>
> Today I wasted some time trying to find the bug in the following piece
> of code:
>
>     (define (syntax-car syntax)
>       (syntax-case syntax () ((car . cdr) #'car)))
>
> Better error reporting in macro-expansion errors might have made it less
> painful, but maybe we can solve the problem itself.
>
> How about making 'foo turn into something like (__quote__ foo), and
> similar for `foo, #'foo, etc.?  Where __quote__ is just a synonym to
> quote, and the original works too.  Ideal would be a symbol that's not
> as noisy (in debug output) but still highly improbable to appear in user
> code and be accidentally shadowed.
>
>
You mean that #'x is synonymous to (syntax x), and that's where the problem
stems from?


> Maybe it would not be standards-compliant in the strict sense, but I
> believe it would be an improvement.
>
> Am I missing any obvious downsides?  Or any subtle ones?
>
>
I think that every lisper should know that 'x is synonymous to (quote x),
and in some contexts it might be desirable to bind a new meaning to the
"quote" form (and this is already done by some libraries, notably in the
(ice-9 match) module).

As to "syntax", the use of #'x is much rarer, and the idea that #'x is
(syntax x) is indeed a bit controversial. But this regards the whole
syntax-case macro system, and I think that it would be more valuable to
think how to fix its flaws, rather than change the very fundamentals of the
language.


Best regards,
M.

[-- Attachment #2: Type: text/html, Size: 2282 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Making apostrophe, backtick, etc. hygienic?
  2015-08-30 12:48 ` Panicz Maciej Godek
@ 2015-08-30 13:16   ` Taylan Ulrich Bayırlı/Kammer
  2015-08-30 13:57     ` Panicz Maciej Godek
  0 siblings, 1 reply; 8+ messages in thread
From: Taylan Ulrich Bayırlı/Kammer @ 2015-08-30 13:16 UTC (permalink / raw)
  To: Panicz Maciej Godek; +Cc: guile-devel

Panicz Maciej Godek <godek.maciek@gmail.com> writes:

> You mean that #'x is synonymous to (syntax x), and that's where the
> problem stems from?

Yup.  I shadow 'syntax', but I don't explicitly shadow "#'".  It gets
shadowed implicitly.  Lexical scoping and hygiene are supposed to let
the programmer forget about such worries.

> I think that every lisper should know that 'x is synonymous to (quote
> x), and in some contexts it might be desirable to bind a new meaning
> to the "quote" form (and this is already done by some libraries,
> notably in the (ice-9 match) module).

One may know, but still forget when sufficiently tired, and/or when
using the word "quote" to mean something conceptually different than the
quoting in lisp.

For instance, some kind of text processing program might give the term
"quote" a specific meaning in the program's problem domain, and once
you're immersed deeply enough in this domain, you might find yourself
naming some function parameter "quote" without giving it a second
thought.  Kind of difficult to explain what I mean, but I know it
happens to me when I'm not careful.  As another example, it also keeps
happening to me that I write code like:

    (syntax-rules ()
      ((_ foo)
       (begin
         ...
         (let ((foo bar))
           ...))))

where I forget that the 'foo' there will not be bound freshly by that
let form, and that despite that I understand how 'syntax-rules' works
very well (externally, not necessarily internally!).  One is just
accustomed to be able to let-bind whatever one wants, and lexical
scoping and hygiene take care of all worries ... except when not. :-)
(In this case it has nothing to do with quote/syntax/etc., just giving
an example of what silly mistakes I can make when not careful.)

(Nowadays I name all my pattern variables <foo> for that reason.  Reads
like BNF too, which is nice.  And I don't see it ever clashing with
record type names in practice.)

> As to "syntax", the use of #'x is much rarer, and the idea that #'x is
> (syntax x) is indeed a bit controversial. But this regards the whole
> syntax-case macro system, and I think that it would be more valuable
> to think how to fix its flaws, rather than change the very
> fundamentals of the language.

Hmm, I'm not sure what flaws of syntax-case you have in mind.  IMO it's
a pretty nice system.  But either way, I don't think making #'foo expand
to (__syntax__ foo), and simply making __syntax__ a synonyms to syntax,
are fundamental changes.  I would have thought it's a rather superficial
change...

> Best regards,
> M.

Kind regards,
Taylan



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Making apostrophe, backtick, etc. hygienic?
  2015-08-30 13:16   ` Taylan Ulrich Bayırlı/Kammer
@ 2015-08-30 13:57     ` Panicz Maciej Godek
  2015-08-30 14:47       ` Taylan Ulrich Bayırlı/Kammer
  0 siblings, 1 reply; 8+ messages in thread
From: Panicz Maciej Godek @ 2015-08-30 13:57 UTC (permalink / raw)
  To: Taylan Ulrich Bayırlı/Kammer; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 5123 bytes --]

2015-08-30 15:16 GMT+02:00 Taylan Ulrich Bayırlı/Kammer <
taylanbayirli@gmail.com>:

> Panicz Maciej Godek <godek.maciek@gmail.com> writes:
>
> > You mean that #'x is synonymous to (syntax x), and that's where the
> > problem stems from?
>
> Yup.  I shadow 'syntax', but I don't explicitly shadow "#'".  It gets
> shadowed implicitly.  Lexical scoping and hygiene are supposed to let
> the programmer forget about such worries.
>
> > I think that every lisper should know that 'x is synonymous to (quote
> > x), and in some contexts it might be desirable to bind a new meaning
> > to the "quote" form (and this is already done by some libraries,
> > notably in the (ice-9 match) module).
>
> One may know, but still forget when sufficiently tired, and/or when
> using the word "quote" to mean something conceptually different than the
> quoting in lisp.
>

You could say that about practically any keyword in Scheme, or for that
matter any other language. The advantage of Scheme is that it really allows
you to redefine any keyword you like. Your point is that quote (and
unquote, and quasiquote, and syntax, and unsyntax, and quasisyntax) is a
reader macro, so one might forget that 'x is really (quote x) -- because
that indeed cannot be infered from the source code.


> For instance, some kind of text processing program might give the term
> "quote" a specific meaning in the program's problem domain, and once
> you're immersed deeply enough in this domain, you might find yourself
> naming some function parameter "quote" without giving it a second
> thought.  Kind of difficult to explain what I mean, but I know it
> happens to me when I'm not careful.


You've got the point, but I think that the only reasonable solution would
be to make the compiler issue warning whenever reader macro identifiers are
being shadowed.


>   As another example, it also keeps
> happening to me that I write code like:
>
>     (syntax-rules ()
>       ((_ foo)
>        (begin
>          ...
>          (let ((foo bar))
>            ...))))
>
> where I forget that the 'foo' there will not be bound freshly by that
> let form, and that despite that I understand how 'syntax-rules' works
> very well (externally, not necessarily internally!).  One is just
> accustomed to be able to let-bind whatever one wants, and lexical
> scoping and hygiene take care of all worries ... except when not. :-)
> (In this case it has nothing to do with quote/syntax/etc., just giving
> an example of what silly mistakes I can make when not careful.)
>
>
Well, misspellings happen all the time, but I think that just as their
consequences can usually be avoided in real life by use of sanity,
unit-testing your code is the best way to make sure that it is sane.


> (Nowadays I name all my pattern variables <foo> for that reason.  Reads
> like BNF too, which is nice.  And I don't see it ever clashing with
> record type names in practice.)
>
> > As to "syntax", the use of #'x is much rarer, and the idea that #'x is
> > (syntax x) is indeed a bit controversial. But this regards the whole
> > syntax-case macro system, and I think that it would be more valuable
> > to think how to fix its flaws, rather than change the very
> > fundamentals of the language.
>
> Hmm, I'm not sure what flaws of syntax-case you have in mind.  IMO it's
> a pretty nice system.


syntax-rules are nice, because they allow to comprehend macro
transformations in terms of textual substitutions (as it is the case with
functional programming), but because they expand in normal (rather than
applicative) order, it's difficult to write more complex macros.
The well-known solution is to use CPS macros (which are very difficult to
comprehend) or Oleg Kiselyov's idea to implement the CK abstract machine in
them.
The third way, often the most intuitive, to influence the order of
expansion, is to use syntax-case. However, if you do so, you can no longer
(in general) analyze the macros in terms of textual substitution. And you
need to use some new weird special forms, like the aforementioned "syntax"

But either way, I don't think making #'foo expand
> to (__syntax__ foo), and simply making __syntax__ a synonyms to syntax,
> are fundamental changes.


Putting the issue with "syntax" aside, making 'foo expand to (__quote__
foo) would be surprising to anyone who actually wanted to shadow "quote".
As I mentioned earlier, there are libraries that make use of the fact that
'x is (quote x). Take a look in here, for example:
http://git.savannah.gnu.org/gitweb/?p=guile.git;a=blob;f=module/ice-9/match.upstream.scm;h=ede1d43c9ff8b085cb5709678c4227f5ecaaa8a5;hb=HEAD#l335

(match '(a b)
  (('a 'b) #t)
  (_ #f))

would no longer evaluate to #t, because the ('a 'b) pattern would actually
be read as ((__quote__ a) (__quote__ b)). You'd need to change all
occurences of "quote" with "__quote__" in the match.upstream.scm (and in
every other library that shadows quote for its purpose) in order to make it
work, thus making Guile non-RnRS-compliant.

[-- Attachment #2: Type: text/html, Size: 7097 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Making apostrophe, backtick, etc. hygienic?
  2015-08-30 13:57     ` Panicz Maciej Godek
@ 2015-08-30 14:47       ` Taylan Ulrich Bayırlı/Kammer
  2015-08-31 11:58         ` Panicz Maciej Godek
  0 siblings, 1 reply; 8+ messages in thread
From: Taylan Ulrich Bayırlı/Kammer @ 2015-08-30 14:47 UTC (permalink / raw)
  To: Panicz Maciej Godek; +Cc: guile-devel

Panicz Maciej Godek <godek.maciek@gmail.com> writes:

> Your point is that quote (and unquote, and quasiquote, and syntax, and
> unsyntax, and quasisyntax) is a reader macro, so one might forget that
> 'x is really (quote x) -- because that indeed cannot be infered from
> the source code.

Yup, exactly.

> You've got the point, but I think that the only reasonable solution
> would be to make the compiler issue warning whenever reader macro
> identifiers are being shadowed.

That's a good idea as well.  It might annoy some users though, when they
really want to shadow 'quote' (or 'syntax').  Dunno.

> Putting the issue with "syntax" aside, making 'foo expand to
> (__quote__ foo) would be surprising to anyone who actually wanted to
> shadow "quote". As I mentioned earlier, there are libraries that make
> use of the fact that 'x is (quote x). Take a look in here, for
> example:
> http://git.savannah.gnu.org/gitweb/?p=guile.git;a=blob;f=module/ice-9/match.upstream.scm;h=ede1d43c9ff8b085cb5709678c4227f5ecaaa8a5;hb=HEAD#l335
>
> (match '(a b)
> (('a 'b) #t)
> (_ #f))
>
> would no longer evaluate to #t, because the ('a 'b) pattern would
> actually be read as ((__quote__ a) (__quote__ b)). You'd need to
> change all occurences of "quote" with "__quote__" in the
> match.upstream.scm (and in every other library that shadows quote for
> its purpose) in order to make it work, thus making Guile
> non-RnRS-compliant.

Hmm, that gets a little complicated, yeah.  Still, in highly RnRS
compliant systems, macros actually match their "literal" inputs by
(hygienic) "bindings" and not the names of identifiers.  I.e., if the
quote and __quote__ identifiers hold the *same binding*, then a macro
that has 'quote' in its literals list will also match '__quote__' for
that literal.  (Magic!)  I seem to remember Guile 2.2 really does this
the pedantically right way, while Guile 2.0 is more lax about it.

This would even help those libraries then.  The user could shadow the
'quote' identifier's binding locally, meaning 'match' is going to reject
it because it's not the binding which 'match' knows, but 'foo will keep
working in 'match' because it will expand to '__quote__' which has not
been shadowed and so still holds the same binding as the 'quote' binding
with which 'match' was defined.

The only RnRS-compliant code that would break is code which itself
shadows 'quote' and expects its shadowing to work with 'foo.  Like:

    (let ((quote -)) '9)  ;=> -9

Dunno if there's any serious Scheme/Guile code out in the wild which
actually relies on this working.

Taylan



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Making apostrophe, backtick, etc. hygienic?
  2015-08-30 14:47       ` Taylan Ulrich Bayırlı/Kammer
@ 2015-08-31 11:58         ` Panicz Maciej Godek
  2015-08-31 13:10           ` Taylan Ulrich Bayırlı/Kammer
  0 siblings, 1 reply; 8+ messages in thread
From: Panicz Maciej Godek @ 2015-08-31 11:58 UTC (permalink / raw)
  To: Taylan Ulrich Bayırlı/Kammer; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 4791 bytes --]

2015-08-30 16:47 GMT+02:00 Taylan Ulrich Bayırlı/Kammer <
taylanbayirli@gmail.com>:

> Panicz Maciej Godek <godek.maciek@gmail.com> writes:
>
> > Your point is that quote (and unquote, and quasiquote, and syntax, and
> > unsyntax, and quasisyntax) is a reader macro, so one might forget that
> > 'x is really (quote x) -- because that indeed cannot be infered from
> > the source code.
>
> Yup, exactly.
>
> > You've got the point, but I think that the only reasonable solution
> > would be to make the compiler issue warning whenever reader macro
> > identifiers are being shadowed.
>
> That's a good idea as well.  It might annoy some users though, when they
> really want to shadow 'quote' (or 'syntax').  Dunno.
>

This could actually be solved by some additional means -- for example, one
could have to write some additional statements that would confirm that he's
aware that the reader macros are being shadowed. For instance

(define-syntax match
  (syntax-rules (.... quote ....)
    ....))

(assert (syntax-shadows? match 'quote)) ;; removes the warning

But to be honest, I don't think that this is a real problem. The problem
manifested itself with the "syntax" form, and not the "quote" form, and I
think the reason for that is not just accidental. The "quote" form is more
common and more commonly used, while the "syntax" form is exotic and
surprising -- especially because everyone unfamiliar would read #' as
"hash-quote" rather than "syntax"


> > Putting the issue with "syntax" aside, making 'foo expand to
> > (__quote__ foo) would be surprising to anyone who actually wanted to
> > shadow "quote". As I mentioned earlier, there are libraries that make
> > use of the fact that 'x is (quote x). Take a look in here, for
> > example:
> >
> http://git.savannah.gnu.org/gitweb/?p=guile.git;a=blob;f=module/ice-9/match.upstream.scm;h=ede1d43c9ff8b085cb5709678c4227f5ecaaa8a5;hb=HEAD#l335
> >
> > (match '(a b)
> > (('a 'b) #t)
> > (_ #f))
> >
> > would no longer evaluate to #t, because the ('a 'b) pattern would
> > actually be read as ((__quote__ a) (__quote__ b)). You'd need to
> > change all occurences of "quote" with "__quote__" in the
> > match.upstream.scm (and in every other library that shadows quote for
> > its purpose) in order to make it work, thus making Guile
> > non-RnRS-compliant.
>
> Hmm, that gets a little complicated, yeah.  Still, in highly RnRS
> compliant systems, macros actually match their "literal" inputs by
> (hygienic) "bindings" and not the names of identifiers.  I.e., if the
> quote and __quote__ identifiers hold the *same binding*, then a macro
> that has 'quote' in its literals list will also match '__quote__' for
> that literal.  (Magic!)  I seem to remember Guile 2.2 really does this
> the pedantically right way, while Guile 2.0 is more lax about it.
>
>
I think that this is the case for R6RS or R7RS, but as far as I can tell,
in R5RS it would be problematic.

The only RnRS-compliant code that would break is code which itself
> shadows 'quote' and expects its shadowing to work with 'foo.  Like:
>
>     (let ((quote -)) '9)  ;=> -9
>
> Dunno if there's any serious Scheme/Guile code out in the wild which
> actually relies on this working.
>
>
You'll never know. While it may seem unlikely to fix quote to mean minus,
in mathematical analysis the symbol is often used to mean the derivative of
a unary function, so it is quite possible that someone would wish to write
in some context

(let ((quote deriv))
  (+ (f x) ('f x) (''f x)))

On the other hand, your soultion would work if someone decided to write

(let ('deriv)
 (+ (f x) ('f x) (''f x)))

(which is IMO more elegant)

Nevertheless, I think that even if 'x would map to (__quote__ x), it could
still happen that someone was using the __double_underscore__ convention in
her code (for some reason), and your allegations would apply to this new
situation as well.

As I said earlier, I think that the problem isn't caused by the fact that
'x is (quote x), because it is likely that every lisp programmer reads 'x
as "quote x", but by the fact that there is this weird "syntax" form (and
its family) which has only one application in Scheme, namely -- syntax-case
macros.

You could ask the question on comp.lang.scheme newsgroup, but I think that
the solution you suggest would only introduce unnecessary divergence from
Lisp and Scheme, and for a dubious reason. Furthermore, while it is common
to use these __underscores__ in C, PHP or Python, it is an alien practice
in the Scheme code base. (Instead of "quote x", you'd need to read 'x as
"underscore underscore quote underscore underscore x", which is unhandy and
brain-damaging)

Regards,
M.

[-- Attachment #2: Type: text/html, Size: 6738 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Making apostrophe, backtick, etc. hygienic?
  2015-08-31 11:58         ` Panicz Maciej Godek
@ 2015-08-31 13:10           ` Taylan Ulrich Bayırlı/Kammer
  0 siblings, 0 replies; 8+ messages in thread
From: Taylan Ulrich Bayırlı/Kammer @ 2015-08-31 13:10 UTC (permalink / raw)
  To: Panicz Maciej Godek; +Cc: guile-devel

Panicz Maciej Godek <godek.maciek@gmail.com> writes:

> I think that this is the case for R6RS or R7RS, but as far as I can
> tell, in R5RS it would be problematic.

I think the R5RS is implicitly silent on that by virtue of not having a
library system.  It says that a literal in a pattern will match "if it
has the same lexical binding" and if an extension to R5RS provides a way
to create different identifiers with the "same lexical binding" then
that wouldn't contradict the standard. :-)

I don't think we should obsess over compliance that much anyway though.
The unhygienic 'foo is one of the few very strange things in Scheme IMO.

> You'll never know. While it may seem unlikely to fix quote to mean
> minus, in mathematical analysis the symbol is often used to mean the
> derivative of a unary function, so it is quite possible that someone
> would wish to write in some context
>
> (let ((quote deriv))
>   (+ (f x) ('f x) (''f x)))
>
> On the other hand, your soultion would work if someone decided to
> write
>
> (let ('deriv)
>   (+ (f x) ('f x) (''f x)))
>
> (which is IMO more elegant)

IMO the rarity of such code, plus the easiness of fixing it, make that a
non-issue.

> Nevertheless, I think that even if 'x would map to (__quote__ x), it
> could still happen that someone was using the __double_underscore__
> convention in her code (for some reason), and your allegations would
> apply to this new situation as well.

That's much less likely, and it needn't be underscores either.  E.g. it
could be %%quote instead.  (Maybe we already have a convention for this,
I don't know.)


Anyway, if people don't like the idea for whatever reason then I won't
push it.  I just thought it would be neat to uphold the hygiene a little
farther, and not make it break when a user binds an identifier that's a
plain word like quote or syntax.

Taylan



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Making apostrophe, backtick, etc. hygienic?
  2015-08-30 12:30 Making apostrophe, backtick, etc. hygienic? Taylan Ulrich Bayırlı/Kammer
  2015-08-30 12:48 ` Panicz Maciej Godek
@ 2015-09-02  2:55 ` Mark H Weaver
  1 sibling, 0 replies; 8+ messages in thread
From: Mark H Weaver @ 2015-09-02  2:55 UTC (permalink / raw)
  To: Taylan Ulrich "Bayırlı/Kammer"; +Cc: guile-devel

taylanbayirli@gmail.com (Taylan Ulrich "Bayırlı/Kammer") writes:

> How about making 'foo turn into something like (__quote__ foo), and
> similar for `foo, #'foo, etc.?

This is part of the standard behavior of 'read', e.g. section 4.3.5 of
the R6RS, and has been for over 50 years.  Lots of existing code assumes
this.  Changing it now is out of the question.

Also, the subject of this thread is misleading, because your proposal
would not make these reader abbreviations hygienic.

> Where __quote__ is just a synonym to quote, and the original works
> too.

Not when some arbitrary code looks at the result of 'read', or inside a
quoted datum like '(nested quote 'x).

     Mark



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-09-02  2:55 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-30 12:30 Making apostrophe, backtick, etc. hygienic? Taylan Ulrich Bayırlı/Kammer
2015-08-30 12:48 ` Panicz Maciej Godek
2015-08-30 13:16   ` Taylan Ulrich Bayırlı/Kammer
2015-08-30 13:57     ` Panicz Maciej Godek
2015-08-30 14:47       ` Taylan Ulrich Bayırlı/Kammer
2015-08-31 11:58         ` Panicz Maciej Godek
2015-08-31 13:10           ` Taylan Ulrich Bayırlı/Kammer
2015-09-02  2:55 ` Mark H Weaver

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).