lilypond-user
[Top][All Lists]
Advanced

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

Re: Scheme learning


From: David Kastrup
Subject: Re: Scheme learning
Date: Mon, 28 May 2018 22:07:51 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.0.50 (gnu/linux)

Robert Schmaus <address@hidden> writes:

> Hi Andrew,
>
> thanks first of all for your mail and the many resources (which I will
> need some time to look through, I think) ... and sorry for the late
> reply, I had two computer-free days, which sometimes really is
> refreshing.
>
> I agree with you - when I looked at the Scheme functions (mainly as
> Snippets) I saw that it's not very complicated. It was just when I
> tried to customise something that I really had to do a lot of
> guesswork how to get this to work. Does this expression return
> something or not? What does "lambda" mean, why does this expression
> need a context and where do I get it from?
>
> Just to illustrate what I mean: To get a bar number, one needs to use
> the apply context function. In the documentation, there's this:
>
> \applyContext
>   #(lambda (x)
>     (format #t "\nWe were called in barnumber ~a.\n"
>      (ly:context-property x 'currentBarNumber)))
>
> So, (ly:context-property x 'currentBarNumber) returns the bar number,
> clear enough.

Given a context x, evaluated at the time where the \applyContext call is
"iterated".

> But how do I get it outside the lambda thing?

There is no current bar number outside of iteration (the interpretation
of a music expression in the sequence of musical time).

> Replacing the format directive with a define directive doesn't work
> because bnum is not know outside.
>
> \applyContext
>   #(lambda (x)
>     (define bnum (ly:context-property x 'currentBarNumber)))
> \set Score.currentBarNumber = #bnum

You can use set! for setting global variables (to be defined at global
scope) but it seems nonsensical to store stuff in a variable instead of
just setting that property.

So something like
\applyContext
  #(lambda (current-context)
    (set! (ly:context-property (ly:context-find current-context 'Score)
                               'currentBarNumber)
          (ly:context-property current-context 'currentBarNumber)))


> Defining the variable outside and assigning a value inside throws no
> error but the value in the last line is 0

> #(define bnum 0)
> \applyContext
>   #(lambda (x)
>     (set! bnum (ly:context-property x 'currentBarNumber)))
> \set Score.currentBarNumber = #bnum

Well, \applyContext and \set are called at the same point of musical
time.  \set is worked on during the start of time step (so that the
settings it establishes are present for other commands) while
\applyContext has its workload defined for the "process-music" stage.
Which means that stuff like the Timing_translator have already run.
Also, \set has completed.  Probably not the most intuitive behavior.

Not actually related to Scheme but rather to the order LilyPond
internals process music.

> In this way, I fiddle around, sometimes I got it to work sometimes not
> and in either case I don't really have a clue why.

Well, to be fair, in this particular case I'll readily admit that
"obvious" is not really a proper description of what happens.

Most of what you guessed was quite right but you weren't able to
appreciate that because of the final spanner in the works (the execution
order) that had rather little to do with your deductions.

> So anyway, as you might have seen, Urs sent me a link to a
> lilypond-specific Scheme manual that he started - I guess I'll work my
> way through that (as well as the "Extending Lilypond" manual)
> first. Maybe then I'm even really hooked to see more of Scheme, who
> knows ...

It won't help for the quirks of this particular case.  I admit I looked
in the code for the details of \applyContext, mostly because I am too
lazy to look in places I know my way around less.

-- 
David Kastrup



reply via email to

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