lilypond-user
[Top][All Lists]
Advanced

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

Re: Lilypond custom chords & Scheme


From: Lukas-Fabian Moser
Subject: Re: Lilypond custom chords & Scheme
Date: Sun, 21 Jun 2020 17:01:06 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.8.0

Hi Dave,

unfortunately I don't have enough time at the moment to think about your underlying problem and what the best solution in LilyPond might be (maybe other people will be willing to chime in), but I can try to answer your specific questions:

First, in the manual, for both define-scheme-function and define-music-function, it seems to say that you need to declare the types of the parameters. So how come 'parser' and 'location' are not specified? I couldn't find anything in the documentation about the first two parameters being the parser and the location?
parser and location were extra arguments that had to be mentioned in the definition of any scheme- or music function, even though they are rarely needed explicitly. They do not have corresponding "type declarations" (to be precise: predicates that are supposed to nod if the parameters the function is called with are of an acceptable type), so it's normal to have two less predicates than formal parameters:

(define-music-function (parser location var1 var2 ... varn) (pred1? pred2? ... predn?) ...)

_But_ changes in LilyPond have made it possible to omit parser/location in most function definitions in the 2.20 and 2.21 versions. If you use a current version of LilyPond, you may just write

(define-music-function (var1 var2 ... varn) (pred1? pred2? ... predn?) ...)

which is a small step for your fingers at the keyboard but a giant leap in intuitiveness of the syntax :-).

The second question is: why the double definition? Why define a music function inside a Scheme function? My first attempts at achieving this before I found the above (which were moderately successful but much more complicated than the above) used only a music function. Does the original author know something I don't about how this all works (my default assumption) or is it unnecessary?
The function you posted is a bit involved in that it defines a function that creates a function. The assignment

voicing = \makevoicing < g a c e a >

assigns the name \voicing to the _result_ of \makevoicing < g a c e a >, which is

(define-music-function (parser location d) (ly:duration?)
                    (map-some-music
                      (lambda (m)
                        (and (ly:duration? (ly:music-property m 'duration))
                             (begin
                                (set! (ly:music-property m 'duration) d)
                                m)))
                      (ly:music-deep-copy m))))
where now m is a music variable containig the chord < g a c e a >.

Hence, \voicing is now a _function_ (in which the chord <g a c e a> is hard-wired) accepting a duration.

The same may be achieved in current LilyPond (2.20 and above) by the \etc idiom:

\version "2.20.0"

chordVoicing =
#(define-music-function (m d) (ly:music? ly:duration?)
   (map-some-music
    (lambda (m)
      (and (ly:duration? (ly:music-property m 'duration))
           (begin
            (set! (ly:music-property m 'duration) d)
            m)))
    (ly:music-deep-copy m)))

voicing = \chordVoicing <g a c e a> \etc % dom7, with 7th in bass

\new Staff {
  \voicing 4 \voicing 8 \voicing 16.
}

That is, you can now define a function accepting multiple parameters and define a "partial" function call inserting only some of these parameters.

HTH
Lukas

reply via email to

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