lilypond-user
[Top][All Lists]
Advanced

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

Re: Context question


From: Jean Abou Samra
Subject: Re: Context question
Date: Sun, 11 Sep 2022 23:22:03 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.2.0

Le 11/09/2022 à 23:01, John Schlomann a écrit :

Can someone please explain why the following won’t work. I want get the current moment at the end of the music expression. Is this not a valid thing to do? Or perhaps I don’t know how to specify the context. This code gives an unbound variable error.

\version "2.22.2"

\score {
  \relative c'' {
    \new Staff {
      a b c d
      #(display (ly:context-current-moment Staff))
    }
  }
}




This code tries to mix two passes of LilyPond's processing that
are separate. First, LilyPond reads the input code, and creates
music objects from it, basically those that you store in variables
when you do

violin = \relative c' { ... }
% \violin is a music expression

Now, suppose that you could do

violinPartI =
\relative c' {
  ...
}

violinPartII =
\relative c' {
  ...
  #(display (ly:context-current-moment Staff))
  ...
}

%% What has been printed at this point?

\score {
  {
    \violinPartI
    \violinPartII
  }
}

How could this work? The current moment of the context at the point
you ask for it won't be determined until the whole score, including
the duration of violinPartI, is known. Yet you are asking it as soon
as violinPartII is read.

A music expression is just, well, an expression. At the time it is
read, nothing special happens. It's just a data structure. There are
no variables in scope ("Staff" is not defined), no execution process.
Scheme code used within a music expression is executed at the moment
the music is read. This just serves to embed a piece of Scheme-generated
music into it, like in

\version "2.22.2"

\score {
  {
    \new Staff {
      #(make-sequential-music
        (map (lambda (i)
               (make-music 'NoteEvent
                           'duration #{ 4 #}
                           'pitch (ly:make-pitch 0 i 0)))
             (iota 20)))
    }
  }
}

What I've done here is putting some Scheme expression that generates
a piece of music that you could have written as { c'4 d'4 e'4 ... }.
This is just creating a piece of music, without any ambient context
from the surrounding music, since that music has not been determined
yet.

Then, _after_ all the music expressions have been read and assembled,
LilyPond will start its "iteration" (also called "translation") process,
and only then contexts and timing start to come into play.

The way to achieve what you are after is to use the \applyContext hook,
which embeds a procedure into the music expression that will be executed
at iteration time. It's documented here:

https://lilypond.org/doc/v2.22/Documentation/extending/context-evaluation

Example:

\version "2.22.2"

\score {
  \relative c'' {
    \new Staff {
      a b c d
      \context Staff
        \applyContext
          #(lambda (context)
             (display (ly:context-current-moment context)))
    }
  }
}


Maybe this will help you understand the different stages of LilyPond's
processing:

https://extending-lilypond.readthedocs.io/en/latest/intro.html#overview-of-lilypond-s-inner-workings-and-how-you-might-hook-in-them

Best,
Jean




reply via email to

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