Two questions below re: (a) looping and (b) random seed.
In order to investigate some other problems I'm having in a large
project (pagination, memory usage) I learned enough scheme (barely) to
define a function that generates a new score with each invocation:
--
\version "2.22.0"
\include "gen-music.ily"
% each invocation of scr generates a new score of different length
pcn = 0
scr = #(define-scheme-function () ()
(set! pcn (1+ pcn))
#{
\score {
\header { piece = \markup{ "Piece " #(number->string pcn) } }
{ \gen-music \bar "|."} }
#} )
--
(The include file, gen-music.ily, is attached, and the above ~MWE is
also attached as MWE-do-scr.ly.)
Question (a):
My main question is how to write a scheme function that will invoke my
scr function N times, where N could be a number like 1000.
So far the only way I know how to do multiple invocations is by
explicitly hard-coding "\scr \scr ..." in blocks and copy/pasting those
blocks.
Looking for a better way, I realized I don't even know how to get one
line of scheme to do 2 invocations (needed for tail recursion
approach). I can make them execute, in some cases, but not to produce
pdf output (never gets to "Interpreting music..."). Part of this may be
#(scr) vs $(scr). The attached MWE file has lots of my failed attempts
commented out (I'm at a teachable moment if someone has a moment to
teach). Or just point me to the right manual page(s).
Question (b):
My secondary question is very simple. How do you set the seed for
scheme's "random" function (used in my gen-music.ily). I'd like to get
the repeatability of a pseudo-random number generator.
TIA,
Jeff
P.S. May you smile when you see the generated music.
\version "2.22.0"
\include "gen-music.ily"
% each invocation of scr generates a new score of different length
pcn = 0
scr = #(define-scheme-function () ()
(set! pcn (1+ pcn))
#{
\score {
\header { piece = \markup{ "Piece " #(number->string pcn) } }
{ \gen-music \bar "|."} }
#} )
% only way I know to repeat so far
\scr \scr \scr \scr \scr \scr \scr \scr \scr \scr % 10
%\scr \scr \scr \scr \scr \scr \scr \scr \scr \scr % 20
%#(scr) % runs but generates no output
%$(scr) % works for one invocation
% guessing at recursive repeat
%#(define scors (lambda (n) (if (= n 1) (scr) ((scr) (scors (- n 1) )))))
%#(scors 2)
% guessing at for-each repeat
%#(for-each (lambda (ignore) (scr)) '(1 2 3 4 5))
% never does "Interpreting music..." (no output)
%#(begin (scr) (scr) (scr))
% does "Interpreting music...[8]" but only outputs "Piece 3"
%$(begin (scr) (scr) (scr))
%#(define mine (list (scr) (scr) (scr)))
%#@mine % error: bad expression type
%#mine % (no output)
%$(make-sequential-music mine) % Wrong type argument in position 1 (expecting Prob): #<Score>
%$mine % error: bad expression type
%$(mine) % GUILE signaled an error for the expression beginning here
%$(list mine) % error: bad expression type
\version "2.22.0"
% some sequential music objects (to be concatenated with variation by gen-music
function)
xa = { g'4. a'8 g'4 f' e' f' g'2 d'4 e' f'2 e'4 f' g'2 g' a'4 g'8 f' e'4 f' g'2
}
xb = { d'4 e' f'4 e' f' g'8 f' e'4 f'8 g' a'4 c'' e''4 d''8 c'' b'4 cis'' d''2 }
xc = { a'4 b' c''4 b' c'' d''8 c'' b'4 c''8 d'' e''2~ e''4 d''8 c'' b'4 cis''
d''2 }
xd = { a'4 b' c''4 b' c'' d''8 c'' b'4 g'8 f' e'4 d' cis'4 a'8 g' a'4 cis''
d''2 }
xe = { d''4 c'' b'4 g'8 f' g'4 b' c''4 d'' e''2 d''4 c''8 b' a'4 b' c''2 }
xf = { g'4 a' bes'4 a' bes' c''8 bes' a'2 b' c''4 b' c'' d''8 c'' b'4 a' bes'2
a'4 g'8 f' e'4 fis' g'2 }
xg = { d'4 e' f'4 e' f' g'8 f' e'4 c''8 b' a'4 g' fis'4 d''8 c'' d''4 fis' g'2 }
xh = { g'4 f' e'4 c''8 bes' c''4 e' f'4 a'8 g' f'4 e' d'2 g' e'4 c' }
% list of sequential music objects
smolist = #(list xa xb xc xd xe xf xg xh)
% to get a scheme list of music elements from a music object
#(define (get-elements mus) (ly:music-property mus 'elements))
% list of element-lists
elists = #(map get-elements smolist)
enum = #(length elists)
% recursively concatenate a range of elists (0 <= m <= n, possibly > enum)
#(define (cat-elists m n)
(let ((elist-m (list-ref elists (modulo m enum))))
(if (< m n) (append elist-m (cat-elists (1+ m) n)) elist-m )))
% generate music by concatenating contiguous members from list.
% i mod enum is the starting position in the list for the next gen-music.
% mincat is the minimum number of concatenations (mincat >= 0)
% maxcat is the max number of concatenations (maxcat >= mincat)
% actual number of cats is random between mincat and maxcat.
i = 0
mincat = 0
maxcat = 9
gen-music = #(define-music-function () ()
(let* ((m i) (n (+ m (+ mincat (random (1+ (- maxcat mincat)))))))
(set! i (1+ n))
(make-sequential-music (cat-elists m n))))