[Top][All Lists]

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

Re: parser variables persist beyond { } scope

From: Mark Polesky
Subject: Re: parser variables persist beyond { } scope
Date: Thu, 30 Jul 2009 23:39:28 -0700 (PDT)

Han-Wen Nienhuys wrote:

> Braces are overloaded in LilyPond.  In some cases they define scopes
> (like \paper and \header), and in other cases, they just group
> syntactic constructs (\book, \score, sequential musics).
> The solution you propose sounds hairy to me. I think you probably
> are looking for a real scoping construct inside music expressions. I
> don't think this is a very neat idea, because these scoping constructs
> will necessarily not nest correctly wrt { } and << >>.

Well, not *inside* music expressions... Werner's idea was to have the
\score block define a scope, in which I presume every slur left-
parenthesis and every simultaneous-expression double left-angle-bracket
would have a matching close. So, a score block would be a good candidate
for allowing the final "}" to reset all parser-variables (that were
defined within that score block) to the value stored outside the block.

I don't imagine that this is easy (or even practical), but it's an
interesting proposition, so I might as well ask around to see if it's

> The confusion
> arises from your use of #(set! .. ), ie. direct interaction with the
> scheme interpreter. It is assumed that people who do this know what
> they are doing.  Note that in 'native' lilypond syntax, this problem
> is nonexistent, since assignments may only occur at toplevel.

I don't think that's true. The use of "set!" seems irrelevant. The
problem of unintended value-inheritance still occurs when using
"define" instead of "set!". The code below is almost verbatim from the
docs. This is the gotcha that I'm trying to fix. The consequences of
this can be aggravating in complex, multi-score projects:

\version "2.13.3"

\score {
  \relative {
    { c1 \afterGrace d1 { c16[ d] } c1 }
    #(define afterGraceFraction (cons 15 16))
    { c1 \afterGrace d1 { c16[ d] } c1 }

\score {
  \relative {
    %% value of "afterGraceFraction" inherited from previous score.
    { c1 \afterGrace d1 { c16[ d] } c1 }
    #(define afterGraceFraction (cons 15 16))
    { c1 \afterGrace d1 { c16[ d] } c1 }

Now maybe the only viable solution is to place the burden on the user
to reset all parser variables manually after they're done with them
in a particular block. But I very much dislike that solution because
it multiplies the user's chances of making a mistake. And a lot of
times, features with unintended consequences are hard to track down.
Many, many things affect spacing, for example - so when I see spacing
that looks wrong in the middle of a huge project, how can I possibly
know where to look? And the realization that the cause of the problem
could be in another score entirely... I really think this needs to be

Does this make more sense?
- Mark


reply via email to

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