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))))

repeat-verses 3 { \tag #'v1 c' \tag #'v2 d' \tag #'v3 e' f' }
%%%

There are some details with your code I’d do differently:

1. Instead of using string-joins use format:
(format #f "v~a" verse)

2. Instead of using begin/define, use let and let* for local bindings:
(let ((versenum ...)) #{ ... #})

%%%
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' }
%%%


Am Freitag, 24. Mai 2024, 07:41:07 MESZ schrieb Kevin Pye:
> So after 56 years of programming I've at last got around to writing some
> Lisp, and of course it doesn't work.
> 
> I'm trying to define a routine repeat-verses which would be used like
> 
> \repeat-verses 3 \music
> 
> which would have the effect of
> 
> \keepWithTag #'v1 \music
> \keepWithTag #'v2 \music
> \keepWithTag #'v3 \music
> 
> I came up with this code:
> 
> 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 #music #}))
>       (iota count 1))))
> 
> which doesn't quite work. It's as though no tags are defined, so anything in
> \music which is surrounded by a tag is omitted.
> 
> Replacing the definition of versenum with (define versenum 'v1) works fine,
> although of course you get three copies of verse one, and replacing  the
> definition of versenum with
> 
>         (define versenum
>          (string->symbol (string-join (list "v" (number->string 1)) "" )))
> 
> (i.e. not using the value of variable verse) also works with three copies of
> verse one.
> 
> So two questions:
>  1. Why doesn't this work; and
>  2. How should I really go about solving this problem?
> Kevin.

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to