guile-user
[Top][All Lists]
Advanced

[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"



reply via email to

[Prev in Thread] Current Thread [Next in Thread]