Hallo,
ich habe mir Deine procedure
one-level mal etwas genauer angesehen.
Wenn man
(write (display-lily-music (make-music 'SequentialMusic 'elements new-music) parser))als zweite Zeile hinzufügt, kann man die einzelnen Rekursionsschritte im Terminal verfolgen. Man erhält:
{ }
#<unspecified>{ c''2 }
#<unspecified>{ c''2 b' }
#<unspecified>{ c''2 b' |
}
#<unspecified>{ c''2 b' |
a' }
#<unspecified>{ c''2 b' |
a' g' }
#<unspecified>{ c''2 b' |
a' g' |
}
#<unspecified>{
c''2 b' |
a' g' |
c'4 d' e' f' |
}
#<unspecified>{
c''2 b' |
a' g' |
c'4 d' e' f' |
{ g' a' \times 2/3 { b' c'' d'' } |
} { e''2 f'' |
}
}
#<unspecified>{
c''2 b' |
a' g' |
c'4 d' e' f' |
{ g' a' \times 2/3 { b' c'' d'' } |
} { e''2 f'' |
} g''1 |
}
#<unspecified>{ }
#<unspecified>{ c''2 }
#<unspecified>{ c''2 b' }
#<unspecified>{ c''2 b' |
}
#<unspecified>{ c''2 b' |
a' }
#<unspecified>{ c''2 b' |
a' g' }
#<unspecified>{ c''2 b' |
a' g' |
}
#<unspecified>{
c''2 b' |
a' g' |
c'4
}
#<unspecified>{
c''2 b' |
a' g' |
c'4 d'
}
#<unspecified>{
c''2 b' |
a' g' |
c'4 d' e'
}
#<unspecified>{
c''2 b' |
a' g' |
c'4 d' e' f'
}
#<unspecified>{
c''2 b' |
a' g' |
c'4 d' e' f' |
}
#<unspecified>{
c''2 b' |
a' g' |
c'4 d' e' f' |
g' a' \times 2/3 { b' c'' d'' } |
}
#<unspecified>{
c''2 b' |
a' g' |
c'4 d' e' f' |
g' a' \times 2/3 { b' c'' d'' } |
e''2 f'' |
}
#<unspecified>{
c''2 b' |
a' g' |
c'4 d' e' f' |
g' a' \times 2/3 { b' c'' d'' } |
e''2 f'' |
g''1
}
#<unspecified>{
c''2 b' |
a' g' |
c'4 d' e' f' |
g' a' \times 2/3 { b' c'' d'' } |
e''2 f'' |
g''1 |
}
#<unspecified>
{
c''2 b' |
a' g' |
c'4 d' e' f' |
g' a' \times 2/3 { b' c'' d'' } |
e''2 f'' |
g''1 |
}Wie man deutlich sieht läuft die Rekursion zweimal durch. Über
elts und über
new-music und verrichtet dabei zum Teil doppelte Arbeit.
Ich habe dann nach einer procedure gesucht, die nur dort in die Tiefe geht, wo verschachtelte Ausdrücke auch vorhanden sind und
unnest-sequential-music geschrieben.
Die Definition für das schon erwähnte
music-map war der Ausgangspunkt.
Dein
sequentialMusic? habe ich übernommen.
Das Musikbeispiel habe ich etwas komplexer gestaltet.
flatten-list stammt aus /scm/lily-library.scm. Dort gibt es jede Menge nützliche Dinge zu entdecken.
\version "2.16.0"
#(define (sequentialMusic? music)
(eq? (ly:music-property music 'name) 'SequentialMusic))
#(define (unnest-sequential-music music)
"
Unnest sequential music.
This procedure returns a list, which should be applied with:
(make-music 'SequentialMusic 'elements (unnest-sequential-music music))
"
(define (helper m lst)
(let ((elts (ly:music-property m 'elements)))
(if (pair? elts)
(set! lst
(map
(lambda (y)
(append
lst
(if (sequentialMusic? y)
(helper y lst)
y)))
elts)))
(flatten-list lst)))
(helper music '()))
unnestSequentialMusic =
#(define-music-function (parser location mus)
(ly:music?)
(make-music 'SequentialMusic 'elements (unnest-sequential-music mus)))
m = {
c''2 b'-1\2---|^"xy" |
a' g' |
<d' f'>1
{ c'4 d' e' f' | }
{
{
{
g'4 a'
\times 2/3 \unnestSequentialMusic { b'4 { c'' } d''} |
}
\repeat volta 2
{ e''2 f'' | }
\alternative {
{ cis''1 }
{ ces''1}
}
}
}
{ g''1 | }
}
\displayLilyMusic
\unnestSequentialMusic \m
Ausdrücke in \times, \repeat, \alternative etc werden nicht "geglättet" können aber einzeln angesprochen werden wie bei \times ... im Musikbeispiel.
Das Ganze ist allerdings noch nicht sehr ausgiebig getestet, das mußt Du selbst machen

Gruß,
Harm