[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: perplexing syntax-rules bug
From: |
Marco Maggi |
Subject: |
Re: perplexing syntax-rules bug |
Date: |
Sat, 20 Dec 2014 08:39:00 +0100 |
Wette, Matthew R (3441) wrote:
> Sorry to bug, I can't figure out why "sval" in the second evaluation
> of "sect" is bound to the "sval" from the first evaluation of "sect".
> Anyone understand? This is guile 2.0.11. -- Matt
(define-syntax sect
(syntax-rules ()
((sect <name> <expr> ...)
(let ((sval '((name . <name>) (title . #f))))
(format #t "new sect: ~a\n" (quote <name>))
(format #t " sval= ~a\n\n" sval)
(assq-set! sval 'title "ABC")
(values)))))
The problem is that ASSQ-SET! mutates the result of the literal
expression:
'((name . <name>) (title . #f))
this problem is not related to SYNTAX-RULES. The form:
'((name . <name>) (title . #f))
is a "literal expression", it is an expression that evaluates to the
datum:
((name . <name>) (title . #f))
every time the literal expression is evaluated, the returned value is
*the* *same* datum; we can think of it as a value that is hard-coded in
the program. Mutating a hard-coded value leads to undefined behaviour
in (almost?) all the Scheme implementations. Given that they must never
be mutated, some Scheme implementations recognise multiple datums that
are equal and just store one instance of them (to save memory); this
happens especially when the code is compiled rather than interpreted or
evaluated at the REPL.
In an ideal Scheme implementation: such literal expressions should
generate values that are marked as immutable, so that attempting to
mutate them raises an exception; this requires a Scheme implementation
that, for every object type, can distinguish between mutable and
immutable instances. This marking would consume memory or precious bits
in tagged pointers, so not all the Scheme implementations do it.
To solve the problem you have to replace:
'((name . <name>) (title . #f))
with:
(list (cons 'name <name>) (cons 'title #f))
which is an expression returning a newly allocated alist at every
evaluation (by definition, LIST and CONS return newly allocated lists
and pairs every time).
HTH
--
"Now feel the funk blast!"
Rage Against the Machine - "Calm like a bomb"