Valentin Petzel <valen...@petzel.at> writes:

> Hello Kevin,
>
> When you call a music expression like \music Lilypond will allways pass a 
> copy 
> of that music object. Thus some music functions assume it is safe to modify 
> the original music object. So when you do
>
> \keepWithTag ... #music
>
> you will first remove everything tagged without v1, then everything tagged 
> without v2 and so on. So in the end only untagged and tagged with everything 
> will persist. Then you get multiple references to that music object.
>
> What you need to do is to copy the music object passed using ly:music-deep-
> copy:
>
> %%%
> repeat-verses =
> #(define-music-function ( count     music  )
>                         ( index? ly:music? )
>    (make-music 'SequentialMusic 'elements
>      (map-in-order
>       (lambda (verse)
>        (begin
>         (define versenum
>          (string->symbol (string-join (list "v" (number->string verse)) "" )))
>          #{ \keepWithTag #versenum #(ly:music-deep-copy music) #})) 
>       (iota count 1))))

Out of shere laziness, I'd be using
$music here instead of #(ly:music-deep-copy music).  $music is the
Scheme equivalent of \music (including making a copy and suffering from
an early evaluation effect).

It is also possible to replace

#{ \keepWithTag #versenum #(ly:music-deep-copy music) #}

with

(keepWithTag versenum (ly:music-deep-copy music))

but there is a slight difference regarding point-and-click behavior and
typesetting-time error messages.  A closer equivalent would be

(ly:set-origin! (keepWithTag versenum (ly:music-deep-copy music (*location*))))

So the #{ ... $xxx #} variant keeps track of a few details behind the
scene that are not relevant for the function itself but that might come
in handy eventually.

> %%%
> repeat-verses =
> #(define-music-function ( count     music  )
>                         ( index? ly:music? )
>    (make-music 'SequentialMusic 'elements
>      (map-in-order
>       (lambda (verse)
>        (let ((versenum (string->symbol (format #f "v~a" verse))))
>          (keepWithTag versenum (ly:music-deep-copy music))))
>       (iota count 1))))
>
> \repeat-verses 3 { \tag #'v1 c' \tag #'v2 d' \tag #'v3 e' f' }
> %%%

There actually is no reason to use `map-in-order' over just `map' here
since the loop body has no side effects.

Your Scheme inner construct does not touch the
point-and-click/error-location data.  That may or may not be what is
desired.  The guesses that #{ $... #} takes in that regard have a
certain chance of being what the user would prefer.

-- 
David Kastrup

Reply via email to