lilypond-user
[Top][All Lists]
Advanced

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

Re: how to define a boolean?


From: Marc Hohl
Subject: Re: how to define a boolean?
Date: Sun, 09 Aug 2009 17:12:38 +0200
User-agent: Thunderbird 2.0.0.22 (X11/20090608)

Carl Sorensen schrieb:

On 8/9/09 1:20 AM, "Marc Hohl" <address@hidden> wrote:

Was there something else you were trying to do?
Yes, I have to change the value of myBool within a
stencil callback.

Like this:

\version "2.13.3"

#(define myBool #f)

myMusicFunc =
#(define-music-function (parser location) ()
    (display "\nIn myMusicFunc\n")
    (display "myBool: ")(display myBool)(newline)
    (set! myBool #t)
    (display "switched to myBool: ")(display myBool)(newline)
    (make-music 'SequentialMusic 'void #t))

#(define-public (slur::boolean grob)
  ;; just a test function to try and switch boolean values
    (display "\nWithin callback\n")
    (display "myBool: ")(display myBool)(newline)
    (if myBool
        (display "Actions for #t go here...")
        (display "Actions for #f go here..."))
    (set! myBool #f)
    (display "myBool: ")(display myBool)(newline)
    (ly:slur::print grob))

\layout {
  \context {
    \Voice
    \override Slur #'stencil = #slur::boolean
  }
}

\relative c'' {
    c4 ( c )
    \myMusicFunc
    c ( c )
    c ( c )
    \myMusicFunc
    c ( c )
}

 From what I see on the console output, the calls of \myMusicFunc
are evaluated first, so myBool is #t  and the callbacks come in action
afterwards (the first slur claims #t, every other slur reads #f), so
apparently they don't influence each other the way I expected them to do.

Ahh, you have now run into an issue with how LilyPond works.   I had read
about it earlier, but had not understood it until just recently (when I was
working on autobeaming stuff).

The *entire* source file is parsed into a music expression (in scheme form).
During the parsing, the music functions are evaluated, and that's when the
global value of myBool is set.

Once the parsing is complete, the engravers act on the parsed music tree.
During this step, the callbacks will be called, and that is the time that
the changes to the value you make in the callbacks will be executed.

So that is why the first value in the callback was #t -- it was left over
from the last call of \myMusicFunc.  Then the remaining values were #f,
because all of the calls to \myMusicFunc had already been evaluated.
Thanks for this detailed explanation! Now I understand (at least I think so...)

Is there any workaround? Mark introduced ly:parser-lookup (earlier in
this thread),
but this doesn't work for the callback, and his proposal to hand over
the boolean
by using it as an additional argument for the callback has the
disadvantage of
having to override the callback again and again every time the boolean
switches.


I thought I had an idea, but it didn't work.

The fundamental problem you have is that you want to set the boolean based
on the parsing sequence and you want to reset the boolean based on the
engraving sequence.

The *specific* behavior you have requested can be achieved by the following:

#(define myBool #f)

myMusicFunc =
#(define-music-function (parser location) ()
   #{
     \once \override Slur #'dummyProperty = ##t
   #})

I didn't know that I can create and use dummy properties; this
could work for my problem.
#(define-public (slur::boolean grob)
  ;; just a test function to try and switch boolean values
    (let ((my-prop (ly:grob-property grob 'dummyProperty #f)))
      (display "\nWithin callback\n")
      (display "my-prop: ")(display my-prop)(newline)
    (if my-prop
        (display "Actions for #t go here...")
        (display "Actions for #f go here..."))
    (set! myBool #f)
    (display "myBool: ")(display myBool)(newline)
    (ly:slur::print grob)))

\layout {
  \context {
    \Voice
    \override Slur #'stencil = #slur::boolean
  }
}

\relative c'' {
    c4 ( c )
    \myMusicFunc
    c ( c )
    c ( c )
    \myMusicFunc
    c ( c )
}


Note that this relies on the setting to #t being a one-time event.  If the
setting to #t needed to be a toggle, it might be harder.  But I think it
could still work by having the effect of the property be to force the global
value to #t, and the global value could be left #t (once it's been forced)
until such time as the callback sets it to #f.

If you can't make this work and would like to share some more specifics, I
might be able to help you.
I will play with your code, and if I run into problems, I will gladly
return to your offer.

Thank you!

Marc
Thanks,

Carl







reply via email to

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