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

Reply via email to