lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Custom engraver to draw frame around notes


From: Jean Abou Samra
Subject: Re: Custom engraver to draw frame around notes
Date: Tue, 04 Apr 2023 02:52:04 +0200
User-agent: Evolution 3.46.4 (3.46.4-1.fc37)

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; 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, 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

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