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: Carl Sorensen
Subject: Re: how to define a boolean?
Date: Sun, 9 Aug 2009 05:34:54 -0600



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.
> 
> 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
   #})

#(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.

Thanks,

Carl





reply via email to

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