Le lundi 03 avril 2023 à 20:12 -0400, Nate Whetsell a écrit :
> Because this engraver doesn’t mention staffs at all, I’m not sure how this is 
> happening or how to fix it, and I’m hoping I’m missing something simple. Any 
> help would be greatly appreciated! A small test program follows.

I see

```
#(lambda (context)
   (let ((span '())
         (stub '())
         (event-drul '(() . ())))
                     ^^^^^^^^^^^
```

then

```
     `((listeners
         (frame-event .
           ,(lambda (engraver event)
             (if (= START (ly:event-property event 'span-direction))
                 (set-car! event-drul event)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
                 (set-cdr! event-drul event)))))
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
```

This is Bad (™). Quoting is a more subtle concept than many people think. For 
example, many beginner/intermediate and even advanced Scheme programmers do not 
realize that

```
$ LC_ALL=C.UTF-8 ~/lilies/2.25.3/bin/lilypond scheme-sandbox
GNU LilyPond 2.25.3 (running Guile 2.2)
Processing `/home/jean/lilies/2.25.3/share/lilypond/2.25.3/ly/scheme-sandbox.ly'
Parsing...
GNU Guile 2.2.7
Copyright (C) 1995-2019 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@(#{ g123}#)> (define (f) (list 'a 'b 'c))
scheme@(#{ g123}#)> (eq? (f) (f))
$1 = #f
scheme@(#{ g123}#)> (define (f2) '(a b c))
scheme@(#{ g123}#)> (eq? (f2) (f2))
$2 = #t
```

When you quote something, you always get the same thing, as per `eq?`, i.e., 
identity. Therefore, the two engraver instances are sharing the same pair of 
events, which is obviously troublesome.

By the way, you can debug Scheme code by adding `#(ly:set-option 
'compile-scheme-code)` (see 
[this](https://lilypond.org/doc/v2.25/Documentation/extending/debugging-scheme-code);
 caveat: does not work on Windows right now). If you do this, you will get a 
Guile error about attempting to mutate a literal pair.

If you read section 3.4 of the 
[R5RS](https://conservatory.scheme.org/schemers/Documents/Standards/R5RS/r5rs.pdf),
 you can find

“In many systems it is desirable for constants (i.e. the val-
ues of literal expressions) to reside in read-only-memory.
To express this, it is convenient to imagine that every
object that denotes locations is associated with a flag
telling whether that object is mutable or immutable. In
such systems literal constants and the strings returned by
symbol->string are immutable objects, while all objects
created by the other procedures listed in this report are
mutable. It is an error to attempt to store a new value
into a location that is denoted by an immutable object.”

Note that “it is an error” means the program is invalid, not that the 
implementation is required to detect the error. Guile does it for byte-compiled 
code (when you use `compile-scheme-code`). It unfortunately doesn't for 
interpreted code, as in the default mode in LilyPond.

The fix here is to change `'(() . ())` to `(cons '() '())` to create a fresh 
pair for each engraver.

Jean

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to