lilypond-user
[Top][All Lists]
Advanced

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

Re: Accessing context properties (e.g. the current key) from a music fun


From: David Nalesnik
Subject: Re: Accessing context properties (e.g. the current key) from a music function?
Date: Fri, 1 May 2015 07:48:17 -0500

Hi Leah,

On Thu, Apr 30, 2015 at 7:28 PM, Leah Velleman <address@hidden> wrote:
To do something like you want, you really would need access to context properties....

Ok — good to know I haven't missed some simple solution. 

It seems like there ought to be some way of smuggling information out of an \applyContext. But I guess there's a variable scope issue that keeps you from doing it straightforwardly:

k = "OOPS"                                                                  
text = #(define-music-function (parser location music) (ly:music?)                   #{                                                                                                                       \applyContext                                                                                                 #(lambda (context)                                                                                           (set! k  (ly:context-property context 'tonic))
      (display k)
    )     
    \transpose #(ly:make-pitch 0 0) #k #music      
  #}                                                      
)                                                                                                                       \score {                                                                                                             \new Staff {                                                                                                       \key a \major                                                                                                   \test { Fa So La fa so }                                                                                 }                                                                                                                     }  

In that code, the (display k) works fine, displaying #<Pitch a>. But then the \transpose #(ly:make-pitch 0 0) #k #music gets ahold of the global definition of #k rather than the local one and so you end up with a type error: expecting pitch, found "OOPS".

So maybe the question is, does Lilypond Scheme have anything like global variables?

Sure.  But even defining the function with a local variable gives the same results:

test =
#(define-music-function (parser location music) (ly:music?)
   (let ((k "ERROR"))
     #{                                                                                                                  
       \applyContext                                                                                             
       #(lambda (context)                                                                                     
          (set! k  (ly:context-property context 'tonic))                                               
          (display k)                                                                                                 
          )                                                                                                                   
       \transpose #(ly:make-pitch 0 0) #k #music
       #(display k)
       #(newline)
     #}                                                                                                                   
     ))

\score {                                                                                                           
  \new Staff {                                                                                                   
    \key a \major                                                      
    \test { a b cis d e }                                                                              
  }                                                                                                                  
}

The problem arises because \applyContext is evaluated later than \transpose.  When music functions do their work, contexts have not been created yet,

The output shows that the original binding of k is in effect when \transpose is called.

Possibly you could just write a music function that firsts sets the key and then transposes everything.  Here's a sketch:

\version "2.19"

test =
#(define-music-function (parser location pitch music) (ly:pitch? ly:music?)
   #{                                                                                                                  
     \key #pitch \major
     \transpose #(ly:make-pitch 0 0) #pitch #music
   #})

\score {                                                                                                           
  \new Staff {                                                      
    \test a { c' d' e' f' g' a' b' c'' }                                                                              
  }                                                                                                                  
}

David


reply via email to

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