Re: need help building a Scheme function
[Sorry! I wrote this two days ago on a train in one of the famous German cell connection dead zones - and then forgot to actually send it later.] Hi Kieren, The last "m" in your innermost (if ...) is unnecessary: As with the difference between "for" and "map" in plain Scheme, the return value of the lambda function in for-some-music gets discarded ("for" functions are supposed to _do_ something, not _return_ something). So your branch stating "... else return m" can be omitted. Excellent. Well, modulo David's correction. :-) It's true that the lambda function in for-some-music isn't supposed to return the music it has produced. But since its return value determines (as a boolean) whether to recurse, we should make sure to - return ##f if our music argument m is not a note-event (but might contain one) - return a true value if we don't want to recurse any further. Since note-events usually don't contain any other music, this might never actually matter, but it is good to also read your code in the note-event case and check which value gets returned in which case. It might be worth noting that an (if condition then-clause) expression without an else-clause returns and unspecified value if condition is #f. https://www.gnu.org/software/guile/manual/html_node/Conditionals.html Next, as you already hinted: If you use the same expression more than once (here (ly:music-property m 'pitch)), it is usually reasonably to store it in a variable, i.e. use (let ...). Why wouldn’t I use let* here? I readhttps://extending-lilypond.gitlab.io/en/scheme/local-variables.html#let-syntax, and unless there’s some big-ticket efficiency problem under the hood, I don’t see why anyone would use let instead of let*. I do not know if there are efficiency differences between let and let* (but I doubt it). Personally, I use let if I don't need let*, since this way, when I re-read my code, I immediately know that the let-assignments do not depend on one another. we rather want a list of pairs (old-pitch . new-pitch) That’s the interface I was thinking of. In order to construct such a list of pairs from two music inputs as above, (map ...) provides a very elegant way. In the case of a simple scale, \adjustPitches scaleIn scaleOut and then post-processing into lists, etc., makes some sense. But what about sending in pairs instead? e.g. \adjustPitches ((ces c) (c b') (e g)) There would be the question of whether the user wants to process each pair consecutively (e.g., all ces become c, then all c [including the old ces] become b', etc.)… Maybe both options made available, with either a switch or optional parameter(s)? The problem is that (ces c), or rather (ces . c), is Scheme syntax (and requires ` and , when ces and c should not be taken as mere symbols), but we don't have note name input in Scheme. So this would actually be something like (list (cons #{ ces #} #{ c #}) (cons #{ c #} #{ b #})) or `((,#{ ces #} . ,#{ c #}) (,#{ c #} . ,#{ b #})) both of which make my brain hurt :-). A way of inputting the pitches in LilyPond syntax might be much more convenient. Possibilites that come to mind might be { ces c e } { c b' g } { ces c c b' e g } {} etc., all of which are comparatively easy to implement (the first one probably being the easiest). Lukas
Re: need help building a Scheme function
Hi Lukas! Thanks for the patient and helpful tutorial(s). :) > The last "m" in your innermost (if ...) is unnecessary: As with the > difference between "for" and "map" in plain Scheme, the return value of the > lambda function in for-some-music gets discarded ("for" functions are > supposed to _do_ something, not _return_ something). So your branch stating > "... else return m" can be omitted. Excellent. > Next, as you already hinted: If you use the same expression more than once > (here (ly:music-property m 'pitch)), it is usually reasonably to store it in > a variable, i.e. use (let ...). Why wouldn’t I use let* here? I read https://extending-lilypond.gitlab.io/en/scheme/local-variables.html#let-syntax, and unless there’s some big-ticket efficiency problem under the hood, I don’t see why anyone would use let instead of let*. > Also some food for thought, if I may: > - What if I want to replace each b by the c _above_ it? Yes, you are thinking what I’m thinking, for the final version. :) > we rather want a list of pairs (old-pitch . new-pitch) That’s the interface I was thinking of. > In order to construct such a list of pairs from two music inputs as above, > (map ...) provides a very elegant way. In the case of a simple scale, \adjustPitches scaleIn scaleOut and then post-processing into lists, etc., makes some sense. But what about sending in pairs instead? e.g. \adjustPitches ((ces c) (c b') (e g)) There would be the question of whether the user wants to process each pair consecutively (e.g., all ces become c, then all c [including the old ces] become b', etc.)… Maybe both options made available, with either a switch or optional parameter(s)? Cheers, Kieren. __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.
Re: need help building a Scheme function
The last "m" in your innermost (if ...) is unnecessary: As with the difference between "for" and "map" in plain Scheme, the return value of the lambda function in for-some-music gets discarded ("for" functions are supposed to _do_ something, not _return_ something). No, it doesn't. It is a boolean that determines whether to recurse (#f) or not (everything else). Of course you're right, my bad. To be more precise: - Plain Scheme (for ...) is indeed not supposed to return something but rather do something. - LilyPond's (for-some-music ...) is intended to i) do something, ii) return a boolean indicating whether the recursion should continue (kind of "is my work done in this branch of music?"). Of course that's what you explained, I just wanted to point out the comparison with standard "for". So @Kieren: In your example you should take care to control the return value of your lambda (in particular, also in the else-branches of your if's.) Lukas
Re: need help building a Scheme function
Hi David, If you don't want to call upon undocumented internals of LilyPond (the (@@ (lily) ...) bit), you can just use [with-output-to-string] Wow, thanks! I hadn't encountered this possibility yet. Also thanks for pointing out the possibility of in-place modification. Lukas
Re: need help building a Scheme function
Hi Kieren, for-some-music does not return music. It works on music in-place. So the last thing in your music function must not be for-some-music but rather the music that you have been working on. So… %%% SNIPPET BEGINS adjustPitch = #(define-music-function (pitchIn pitchOut music) (ly:pitch? ly:pitch? ly:music?) (for-some-music (lambda (m) (if (music-is-of-type? m 'note-event) (if (and (= (ly:pitch-notename (ly:music-property m 'pitch)) (ly:pitch-notename pitchIn)) (= (ly:pitch-alteration (ly:music-property m 'pitch)) (ly:pitch-alteration pitchIn))) (ly:music-set-property! m 'pitch (ly:make-pitch (ly:pitch-octave (ly:music-property m 'pitch)) (ly:pitch-notename pitchOut) (ly:pitch-alteration pitchOut))) m) #f)) music) music) testmusic = \fixed c' { c4 d es e f g c' es' eis } { \testmusic } { \adjustPitch ees e \testmusic } %%% SNIPPET ENDS ?? The last "m" in your innermost (if ...) is unnecessary: As with the difference between "for" and "map" in plain Scheme, the return value of the lambda function in for-some-music gets discarded ("for" functions are supposed to _do_ something, not _return_ something). So your branch stating "... else return m" can be omitted. Next, as you already hinted: If you use the same expression more than once (here (ly:music-property m 'pitch)), it is usually reasonably to store it in a variable, i.e. use (let ...). Also some food for thought, if I may: - What if I want to replace each b by the c _above_ it? - I've been thinking about a conventient user interface. If I understand you correctly, you aim for something like a list of input-pitches and a list of output-pitches, both preferably given as music, so we can do \adjustPitch { c d e } { fis e d } \music meaning: turn c into fis, d into e, and e into d. If I'm right, you'll probably be able to make good use of (music-pitches ...). Also, for search-and-replace tasks in Scheme, using an association list (alist) as a dictionary is often convenient. This would mean we rather want a list of pairs (old-pitch . new-pitch). In order to construct such a list of pairs from two music inputs as above, (map ...) provides a very elegant way. See also: https://www.gnu.org/software/guile/manual/html_node/Association-Lists.html https://www.gnu.org/software/guile/manual/html_node/List-Mapping.html Lukas
Re: need help building a Scheme function
Hi David, > for-some-music does not return music. It works on music in-place. So > the last thing in your music function must not be for-some-music but > rather the music that you have been working on. So… %%% SNIPPET BEGINS adjustPitch = #(define-music-function (pitchIn pitchOut music) (ly:pitch? ly:pitch? ly:music?) (for-some-music (lambda (m) (if (music-is-of-type? m 'note-event) (if (and (= (ly:pitch-notename (ly:music-property m 'pitch)) (ly:pitch-notename pitchIn)) (= (ly:pitch-alteration (ly:music-property m 'pitch)) (ly:pitch-alteration pitchIn))) (ly:music-set-property! m 'pitch (ly:make-pitch (ly:pitch-octave (ly:music-property m 'pitch)) (ly:pitch-notename pitchOut) (ly:pitch-alteration pitchOut))) m) #f)) music) music) testmusic = \fixed c' { c4 d es e f g c' es' eis } { \testmusic } { \adjustPitch ees e \testmusic } %%% SNIPPET ENDS ?? Thanks, Kieren. __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.
Re: need help building a Scheme function
Kieren MacMillan writes: > I tried a few times, but got errors (about returning > unspecified). Hints appreciated. for-some-music does not return music. It works on music in-place. So the last thing in your music function must not be for-some-music but rather the music that you have been working on. -- David Kastrup
Re: need help building a Scheme function
Hi David, > This will also adjust eis and eses to e. Note names are numbers and can > be compared with = . (make-music 'NoteEvent m) is silly and creates an > unnecessary copy. You can just use m instead. Thanks — current version: %%% SNIPPET BEGINS \version "2.25.11" adjustPitch = #(define-music-function (pitchIn pitchOut music) (ly:pitch? ly:pitch? ly:music?) (music-map (lambda (m) (if (music-is-of-type? m 'note-event) (if (and (= (ly:pitch-notename (ly:music-property m 'pitch)) (ly:pitch-notename pitchIn)) (= (ly:pitch-alteration (ly:music-property m 'pitch)) (ly:pitch-alteration pitchIn))) (ly:music-set-property! m 'pitch (ly:make-pitch (ly:pitch-octave (ly:music-property m 'pitch)) (ly:pitch-notename pitchOut) (ly:pitch-alteration pitchOut))) m) #f) m) music)) testmusic = \fixed c' { c4 d es e f g c' es' eis' } { \testmusic } { \adjustPitch ees e \testmusic } %%% SNIPPET ENDS Q: Is there a more efficient way to test for note name and alteration independent of octave? > If you do, you don't replace any music, so music-map is unnecessary. > This can be better done with for-some-music . I tried a few times, but got errors (about returning unspecified). Hints appreciated. As for next step(s): I’m thinking some let-ing would make sense? Thanks, Kieren. __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.
Re: need help building a Scheme function
Kieren MacMillan writes: > Hi again, > >> There is no necessity to return a new NoteEvent; you can just change >> pitch on the existing one. >> >> Music functions are allowed to modify their music arguments in place. > > This is what I have so far, which appears to do what I want: > > %%% SNIPPET BEGINS > \version "2.25.11" > > adjustPitch = > #(define-music-function (pitchIn pitchOut music) (ly:pitch? ly:pitch? > ly:music?) >(music-map > (lambda (m) > (if (music-is-of-type? m 'note-event) > (if (equal? (ly:pitch-notename (ly:music-property m 'pitch)) > (ly:pitch-notename pitchIn)) > (ly:music-set-property! m 'pitch (ly:make-pitch > (ly:pitch-octave (ly:music-property m 'pitch)) (ly:pitch-notename pitchOut) > 0)) > (make-music 'NoteEvent m)) > (ly:message "Not of type")) > m) > music)) > > \adjustPitch ees e \fixed c' { c4 d es f g c' es' } > %%% SNIPPET ENDS > > Comments before I move to the next step…? This will also adjust eis and eses to e. Note names are numbers and can be compared with = . (make-music 'NoteEvent m) is silly and creates an unnecessary copy. You can just use m instead. If you do, you don't replace any music, so music-map is unnecessary. This can be better done with for-some-music . -- David Kastrup
Re: need help building a Scheme function
Hi again, > There is no necessity to return a new NoteEvent; you can just change > pitch on the existing one. > > Music functions are allowed to modify their music arguments in place. This is what I have so far, which appears to do what I want: %%% SNIPPET BEGINS \version "2.25.11" adjustPitch = #(define-music-function (pitchIn pitchOut music) (ly:pitch? ly:pitch? ly:music?) (music-map (lambda (m) (if (music-is-of-type? m 'note-event) (if (equal? (ly:pitch-notename (ly:music-property m 'pitch)) (ly:pitch-notename pitchIn)) (ly:music-set-property! m 'pitch (ly:make-pitch (ly:pitch-octave (ly:music-property m 'pitch)) (ly:pitch-notename pitchOut) 0)) (make-music 'NoteEvent m)) (ly:message "Not of type")) m) music)) \adjustPitch ees e \fixed c' { c4 d es f g c' es' } %%% SNIPPET ENDS Comments before I move to the next step…? Thanks, Kieren. __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.
Re: need help building a Scheme function
Lukas-Fabian Moser writes: > Elaborating on David's explanation, it might be instructive to study the > output of: > > \version "2.25.9" > > mappingFunction = > #(define-music-function (music) (ly:music?) >(music-map > (lambda (m) > (ly:message "Considering music:\n~a\n-\n" > ((@@ (lily) music->lily-string) m)) > m) > music)) > > \mappingFunction > \new PianoStaff > << > \new Staff \relative { c'4 d e c } > \new Staff \relative { c' g c c } >>> If you don't want to call upon undocumented internals of LilyPond (the (@@ (lily) ...) bit), you can just use \version "2.25.9" mappingFunction = #(define-music-function (music) (ly:music?) (music-map (lambda (m) (ly:message "Considering music:~a-\n" (with-output-to-string (lambda () (displayLilyMusic m m) music)) \mappingFunction \new PianoStaff << \new Staff \relative { c'4 d e c } \new Staff \relative { c' g c c } >> -- David Kastrup
Re: need help building a Scheme function
Lukas-Fabian Moser writes: > But: Whether you use music-map or map-some-music, your helper function > (your lambda) is expected to return the new music into which the given > argument m should be transformed. So in any case, your lambda function > should return music - in the trivial case, it could return m itself > without change, but in the long run, you want to return a new > note-event, i.e. (make-music 'NoteEvent ...). > > For this, it will come in handy that it's possible to do > > (make-music 'NoteEvent m) > > i.e. create a new NoteEvent that takes its 'pitch (which you're going to > overwrite using an additional 'pitch ), 'articulation etc. > properties from m. (This is explained somewhere in Jean's guide.) There is no necessity to return a new NoteEvent; you can just change pitch on the existing one. Music functions are allowed to modify their music arguments in place. -- David Kastrup
Re: need help building a Scheme function
Hi Kieren, Am 21.06.24 um 20:25 schrieb Kieren MacMillan: Hi all, Thank you for the rapid-iteration non-isochronous Scheme class! :) Before I do the next step, is this optimal at this point? %%% SNIPPET BEGINS \version "2.25.11" adjustPitch = #(define-music-function (pitchIn pitchOut music) (ly:pitch? ly:pitch? ly:music?) (music-map (lambda (m) (if (music-is-of-type? m 'note-event) (ly:message "Pitch is: ~a" (ly:music-property m 'pitch)) #f) m) music)) \adjustPitch es es \fixed c' { c4 d e f g a b c' } %%% SNIPPET ENDS While it's possible to use music-map, I'd still recommend map-some-music: Instead of considering all the various music objects in a tree (and then specialising to only considering note events), map-some-music is tailor-made for applications where we want to reach a specific type of music objects in our recursion and then, in each case, declaring the job done, i.e. not recursing any further. (The actual difference should be very small, since also music-map can't help but stop recursing at note-events, since these don't contain other music objects.) But: Whether you use music-map or map-some-music, your helper function (your lambda) is expected to return the new music into which the given argument m should be transformed. So in any case, your lambda function should return music - in the trivial case, it could return m itself without change, but in the long run, you want to return a new note-event, i.e. (make-music 'NoteEvent ...). For this, it will come in handy that it's possible to do (make-music 'NoteEvent m) i.e. create a new NoteEvent that takes its 'pitch (which you're going to overwrite using an additional 'pitch ), 'articulation etc. properties from m. (This is explained somewhere in Jean's guide.) Lukas
Re: need help building a Scheme function
Hi Lukas, > Elaborating on David's explanation, it might be instructive to study the > output of: > [snip] > In short: music-map really considers every music object in a music tree. That was instructive — thanks! Kieren. __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.
Re: need help building a Scheme function
Hi Kieren, I’m a little confused that the output of %%% SNIPPET BEGINS \version "2.25.11" adjustPitch = #(define-music-function (pitchIn pitchOut music) (ly:pitch? ly:pitch? ly:music?) (music-map (lambda (m) (ly:message "Pitch is: ~a" (ly:music-property m 'pitch)) m) music)) \adjustPitch es es \fixed c' { c4 d e f g a b c' } %%% SNIPPET ENDS is Pitch is: # Pitch is: # Pitch is: # Pitch is: # Pitch is: # Pitch is: # Pitch is: # Pitch is: # Pitch is: () Pitch is: () What is causing the last two output lines? Elaborating on David's explanation, it might be instructive to study the output of: \version "2.25.9" mappingFunction = #(define-music-function (music) (ly:music?) (music-map (lambda (m) (ly:message "Considering music:\n~a\n-\n" ((@@ (lily) music->lily-string) m)) m) music)) \mappingFunction \new PianoStaff << \new Staff \relative { c'4 d e c } \new Staff \relative { c' g c c } >> In short: music-map really considers every music object in a music tree. Lukas
Re: need help building a Scheme function
Hi David, > To say something is "optimal", you have to state your objective. I guess the immediate objective was to output [in the log] a list of pitches given the 'music' input. > music-map is used for changing music, and you don't appear to do any > useful changes to the music. In fact, you replace note events with > *undefined* which appears comparatively useless. > > So what are you trying to achieve here? The longer-term objective is to write \adjustMusic es e { c d es f g c' es' } and get { c d e f g c' e' } i.e., turn all E flats [at any octave] into E naturals. Thanks, Kieren. __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.
Re: need help building a Scheme function
Kieren MacMillan writes: > Hi all, > > Thank you for the rapid-iteration non-isochronous Scheme class! :) > > Before I do the next step, is this optimal at this point? > > %%% SNIPPET BEGINS > \version "2.25.11" > > adjustPitch = > #(define-music-function (pitchIn pitchOut music) (ly:pitch? ly:pitch? > ly:music?) >(music-map > (lambda (m) > (if (music-is-of-type? m 'note-event) > (ly:message "Pitch is: ~a" (ly:music-property m 'pitch)) > #f) > m) > music)) > > \adjustPitch es es \fixed c' { c4 d e f g a b c' } > %%% SNIPPET ENDS To say something is "optimal", you have to state your objective. music-map is used for changing music, and you don't appear to do any useful changes to the music. In fact, you replace note events with *undefined* which appears comparatively useless. So what are you trying to achieve here? -- David Kastrup
Re: need help building a Scheme function
Hi all, Thank you for the rapid-iteration non-isochronous Scheme class! :) Before I do the next step, is this optimal at this point? %%% SNIPPET BEGINS \version "2.25.11" adjustPitch = #(define-music-function (pitchIn pitchOut music) (ly:pitch? ly:pitch? ly:music?) (music-map (lambda (m) (if (music-is-of-type? m 'note-event) (ly:message "Pitch is: ~a" (ly:music-property m 'pitch)) #f) m) music)) \adjustPitch es es \fixed c' { c4 d e f g a b c' } %%% SNIPPET ENDS Thanks, Kieren. __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.
Re: need help building a Scheme function
Hi David, > If you want to only look at note events, you need to check for them > yourself. music-map is not discriminating. Ah! Lovely Socratic lesson. :) Thanks, Kieren. __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.
Re: need help building a Scheme function
Kieren MacMillan writes: > Hi again, > > I’m a little confused that the output of > > %%% SNIPPET BEGINS > \version "2.25.11" > > adjustPitch = > #(define-music-function (pitchIn pitchOut music) (ly:pitch? ly:pitch? > ly:music?) >(music-map > (lambda (m) > (ly:message "Pitch is: ~a" (ly:music-property m 'pitch)) m) > music)) > > \adjustPitch es es \fixed c' { c4 d e f g a b c' } > %%% SNIPPET ENDS > > is > > Pitch is: # > Pitch is: # > Pitch is: # > Pitch is: # > Pitch is: # > Pitch is: # > Pitch is: # > Pitch is: # > Pitch is: () > Pitch is: () > > What is causing the last two output lines? Well, what do you think should be the pitch of { c4 d e f g a b c' } and of \fixed c' { c4 d e f g a b c' } ? If you want to only look at note events, you need to check for them yourself. music-map is not discriminating. -- David Kastrup
Re: need help building a Scheme function
Hi Timothy, > Your lambda function for the mapping returns the value of ly:message, which > is #. You need to return some music. Changing the lambda > function to > (lambda (m) > (ly:message "Pitch is: ~a" (ly:music-property m 'pitch)) m) > maps the music to itself without any changes. Oh! I see that now. Thanks! Kieren. __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.
Re: need help building a Scheme function
Hi again, I’m a little confused that the output of %%% SNIPPET BEGINS \version "2.25.11" adjustPitch = #(define-music-function (pitchIn pitchOut music) (ly:pitch? ly:pitch? ly:music?) (music-map (lambda (m) (ly:message "Pitch is: ~a" (ly:music-property m 'pitch)) m) music)) \adjustPitch es es \fixed c' { c4 d e f g a b c' } %%% SNIPPET ENDS is Pitch is: # Pitch is: # Pitch is: # Pitch is: # Pitch is: # Pitch is: # Pitch is: # Pitch is: # Pitch is: () Pitch is: () What is causing the last two output lines? Thanks, Kieren. __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.
Re: need help building a Scheme function
On 21/06/2024 17:36, Kieren MacMillan wrote: Hi Lukas! All right… already back for more specific help. I struggled with map-some-music, and failed. Scanned through Jean’s [amazing] “Extending” docs — yes, yes, I need to RTM on that one, page-by-page! — and found an example with music-map, so tried that instead. Also failed. Your lambda function for the mapping returns the value of ly:message, which is #. You need to return some music. Changing the lambda function to (lambda (m) (ly:message "Pitch is: ~a" (ly:music-property m 'pitch)) m) maps the music to itself without any changes. -- Timothy Lanfear, Bristol, UK.
Re: need help building a Scheme function
Hi Lukas! All right… already back for more specific help. I struggled with map-some-music, and failed. Scanned through Jean’s [amazing] “Extending” docs — yes, yes, I need to RTM on that one, page-by-page! — and found an example with music-map, so tried that instead. Also failed. %%% SNIPPET BEGINS \version "2.25.11" adjustPitch = #(define-music-function (pitchIn pitchOut music) (ly:pitch? ly:pitch? ly:music?) (music-map (lambda (m) (ly:message "Pitch is: ~a" (ly:music-property m 'pitch))) music)) melody = { c'2 g'2 es'2. d'4 | c' es' d' c' | b d' g2 } \adjustPitch es es \fixed c' { c d e f g a b c' } %%% SNIPPET ENDS Helps/Hints appreciated. Kieren __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.
Re: need help building a Scheme function
Hi L-F! >> Is map-some-music the correct next move? > Yes. Thanks! > I take it you're only asking for confirmation you're on the right track? :-) Correct. I’ll try to ask more specific questions when I need more than confirmation. > So I only suggest use the ly:pitch? predicate for pitchIn/pitchOut instead of > ly:music?. Good point. I *think* I eventually want to allow a set (array?) of pitches in/out, but for now, I’ll start the input as small as the output. Thanks! Kieren. __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.
Re: need help building a Scheme function
Hi Kieren, Am 21.06.24 um 16:39 schrieb Kieren MacMillan: %%% SNIPPET BEGINS \version "2.25.11" adjustPitch = #(define-music-function (pitchIn pitchOut music) (ly:music? ly:music? ly:music?) (ly:message "Pitch is: ~a" (ly:pitch-notename (ly:music-property pitchIn 'pitch))) music) melody = { c'2 g'2 es'2. d'4 | c' es' d' c' | b d' g2 } \adjustPitch es es \fixed c' { c d e f g a b c' } %%% SNIPPET ENDS This does exactly what it says on the can. Now I want to “map” the message [stand-in] function to the music provided, so it outputs the pitch for each note in the 'music' input. Is map-some-music the correct next move? Yes. I take it you're only asking for confirmation you're on the right track? :-) So I only suggest use the ly:pitch? predicate for pitchIn/pitchOut instead of ly:music?. Lukas
need help building a Scheme function
Hey list! Trying to work up to being a bigger and better contributor to The ’Pond. Found and copied that “transpose major to minor” scale function in the previous thread I contributed to, but (a) don’t really know if it’s the best way to do what the OP wanted, (b) thought it might be overkill for what the OP wanted, and (c) figured writing another function attacking the same problem with a slightly different approach might be a good way to climb the learning curve. So… I‘m writing a function called \adjustPitch, where \adjustPitch e es { c d e f g c' e' } should output { c d es f g c' es' } Started like this: %%% SNIPPET BEGINS \version "2.25.11" adjustPitch = #(define-music-function (pitchIn pitchOut music) (ly:music? ly:music? ly:music?) (ly:message "Pitch is: ~a" (ly:pitch-notename (ly:music-property pitchIn 'pitch))) music) melody = { c'2 g'2 es'2. d'4 | c' es' d' c' | b d' g2 } \adjustPitch es es \fixed c' { c d e f g a b c' } %%% SNIPPET ENDS This does exactly what it says on the can. Now I want to “map” the message [stand-in] function to the music provided, so it outputs the pitch for each note in the 'music' input. Is map-some-music the correct next move? Thanks, Kieren. __ My work day may look different than your work day. Please do not feel obligated to read or respond to this email outside of your normal working hours.