Jean Abou Samra <j...@abou-samra.fr> writes: > Alternatively, you can do it more like you were envisioning, but for > technical reasons, you have to start the Scheme code with $ , not # , > and you also have to include an extra \midi { } around the \context > blocks (basically because \context outside \layout or \midi is a > different command).
> The # vs $ issue is explained here: > https://extending-lilypond.gitlab.io/en/extending/lily-and-scheme.html#hash-vs-dollar No, it isn't. What happens here is actually not as much a "technical reason" as a design decision. The difference between $ and # explained in the manual entry is orthogonal to it. Here is the rundown: $ produces a token category based on the type of the expression. That means that the type of the expression can change the way the parser parses an expression, and that can be important since the parser may use lookahead to make its decisions, and that may mean that the type of the token (and thus the underlying expression) may need to be known before the previous expression is given its place in the grammar. # does produce a single token category. That means that the parsing can go ahead without even knowing the value of the expression, and the expression is only evaluated once its value is actually needed, making for more predictable evaluation order. That much is sort of in the manual. But what isn't there is that whenever # is going to be accepted, there must be an explicit rule in the grammar accepting it, and that essentially means that when that rule is considered applicable, the grammar is fixed. That still is sort of in the manual. But here is where the design decision comes into play: Scheme may be executed for the purpose of creating a side effect, like assigning a value to a variable. When a Scheme function is being called, it doesn't know whether its return value is going to get used for anything, and a Scheme function executed for its side effect may or may not return a meaningful value. The most prominent side effect is a variable assignment. So as kind of a design rule, at any place in the grammar where you could conceivably write an assignment, the value returned by #... is getting ignored because the expression may only have been called for its side effect, like an assigment. Now $ should never be called just for a side effect (because it is kind of a sledgehammer you should not be using unnecessarily). Function calls introduced by \ are explicitly declared to be of the kind where LilyPond knows when it is supposed to be using the return value. And calling a variable by its name \... does not cause a side effect, so it is safe to assume that you are not invoking its name for the purpose of getting a side effect. So this "I am ignoring the result in contexts where assignments may occur" rule only is made to affect # as a way of invoking Scheme expressions. Where and how should we document/put this rationale so that future contributors and power users are able to understand the current behavior and make qualified decisions about future behavior? I am not sold on this being the best/simplest/most logical that LilyPond can be made to behave. But at the current point of time, I don't know how to do better. And when someone wants to change it, I'd like them to be aware of the rationale behind the current behavior. -- David Kastrup