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

Reply via email to