2

I have some general questions regarding calling a scheme function which I will ask using the following example code (which gives no errors and produces an output pdf):

\version "2.20.0"

pageSong = 
#(define-scheme-function
   (title music)
   (string? ly:music?)
      #{
        \bookpart { 
          \header {
            title = $title
          } 
          \score {
            $music
            \layout {}
          }
        }
      #})

title = "myTitle"
music = { { c' c' c' c'} \addlyrics { one two three four }}
foo = 1
$(pageSong title music)
  • If I remove the line foo = 1, I will get a compilation error saying Unbound variable: music. Why? And why does it not occur when I have that line?

  • If I replace $ by #, no error occurs (even if the foo = 1 line is missing), but no output is created either. Why?

  • This says:

You call a scheme function from LilyPond by writing its name preceded by \, followed by its arguments.

But writing \pageSong \title \music or \pageSong $title $music or \pageSong title music gives the error message bad expression type during compilation. So what is the correct syntax that was meant in the linked source?

5

What happens with the code

music = { ... }
$(pageSong title music)

is that the LilyPond parser scans the input just after the music expression { ... }, because if there were something like \addlyrics, that would affect it. The dollar introduces an expression that is evaluated immediately as soon as it is read, as opposed to the hash. So in this case, the Scheme code execution happens too early, before the assignment has completed.

The usual way to insert Scheme code is with the hash, which does not have this effect. But with the hash, the parser has to do more work to recognize expression types because it cannot see the value in advance, so this only works in certain contexts (most of them, but not all of them; I do not actually know if recognizing embedded \bookpart blocks would be feasible or not).

Here, all you have to do is to let the bookpart be processed by calling toplevel-bookpart-handler yourself on it rather than relying on this being done by the parser.

\version "2.22.1"

pageSong =
#(define-void-function (title music) (string? ly:music?)
   (toplevel-bookpart-handler
      #{
        \bookpart {
          \header {
            title = $title
          }
          \score {
            $music
            \layout {}
          }
        }
      #}))

title = "myTitle"
music = { { c' c' c' c'} \addlyrics { one two three four }}
\pageSong \title \music

The page https://extending-lilypond.readthedocs.io/en/latest/lily-and-scheme.html#hash-vs-dollar has some amount of information.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.