On Tue, Oct 30, 2018 at 12:55 AM Mark H Weaver <
mhw@netris.org> wrote:
More precisely, it is a literal
identifier recognized by 'match' and related macros, in the same sense
that 'else' and '=>' are literal identifiers recognized by the 'cond'
macro.
R5RS section 4.3.2 (Pattern language) specifies how these literal
identifiers are to be compared with identifiers found in each macro use:
Identifiers that appear in <literals> are interpreted as literal
identifiers to be matched against corresponding subforms of the
input. A subform in the input matches a literal identifier if and
only if it is an identifier and either both its occurrence in the
macro expression and its occurrence in the macro definition have
the same lexical binding, or the two identifiers are equal and both
have no lexical binding.
The implication is that these literal identifiers such as 'else', '=>'
and '$' lose their special meaning in any environment where they are
bound, unless the same binding is visible in the corresponding macro
definition environment. R6RS and R7RS also specify this behavior.
For example:
--8<---------------cut here---------------start------------->8---
mhw@jojen ~$ guile
GNU Guile 2.2.3
Copyright (C) 1995-2017 Free Software Foundation, Inc.
Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.
Enter `,help' for help.
scheme@(guile-user)> ,use (ice-9 match)
scheme@(guile-user)> ,use (srfi srfi-9)
scheme@(guile-user)> (define-record-type <foo> (make-foo a b) foo? (a foo-a) (b foo-b))
scheme@(guile-user)> (match (make-foo 1 2) (($ <foo> a b) (+ a b)))
$1 = 3
scheme@(guile-user)> (define $ 'blah)
scheme@(guile-user)> (match (make-foo 1 2) (($ <foo> a b) (+ a b)))
<unnamed port>:6:0: Throw to key `match-error' with args `("match" "no matching pattern" #<<foo> a: 1 b: 2>)'.
Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]>
--8<---------------cut here---------------end--------------->8---
Incidentally, this does *not* throw an error in master (unless I made some mistake in this late hour), which then is a bug!
I now looked at this a bit more. It turns out that the difference is not between stable-2.2 and master, but between REPL and load. While I can reproduce the above also in master, if I instead load it (attached file matchcoll.scm), I get no error!
Also, the following file (attached as "elsetest.scm"):
------------------------------
(display (cond (else #t)))
(newline)
(define else #f)
(display (cond (else #t)))
(newline)
------------------------------
gives the results #t and #<unspecified>, as expected, in the REPL, but if I load the file, I instead get:
scheme@(guile-user)> (load "elsetest.scm")
/home/mdj/guile/elsetest.scm:7:0: Unbound variable: else
If I load it into Chez Scheme, I get:
#t
#<void>
as expected.
Maybe someone more knowledgeable than myself could sort out what out of this is a bug?
Also, I have to rant a bit about R5RS section 4.3.2. What a mess this is! To have the literals influenced by bindings outside goes against the spirit of lexical binding, in my opinion, where the idea is to be able to judge the outcome of the code from looking at it locally.
Best regards,
Mikael