[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Scheme function question
From: |
Thomas Morley |
Subject: |
Re: Scheme function question |
Date: |
Sat, 23 Nov 2013 02:21:05 +0100 |
2013/11/22 David Kastrup <address@hidden>:
> #(defmacro-public make-relative (variables reference music)
> "The list of pitch or music variables in @var{variables} is used as
> a sequence for creating relativable music from @var{music}.
>
> When the constructed music is used outside of @code{\\relative}, it
> just reflects plugging in the @var{variables} into @var{music}.
>
> The action inside of @code{\\relative}, however, is determined by
> first relativizing the surrogate @var{reference} with the variables
> plugged in and then using the variables relativized as a side effect
> of relativizing @var{reference} for evaluating @var{music}.
>
> Since pitches don't have the object identity required for tracing the
> effect of the reference call, they are replaced @emph{only} for the
> purpose of evaluating @var{reference} with simple pitched note events.
>
> The surrogate @var{reference} expression has to be written with that
> in mind. In addition, it must @emph{not} contain @emph{copies} of
> music that is supposed to be relativized but rather the
> @emph{originals}. This @emph{includes} the pitch expressions. As a
> rule, inside of @address@hidden@address@hidden variables must @emph{only} be
> introduced using @code{#}, never via the copying construct @code{$}.
> The reference expression will usually just be a sequential or chord
> expression naming all variables in sequence, implying that following
> music will be relativized according to the resulting pitch of the last
> or first variable, respectively.
>
> Since the usual purpose is to create more complex music from general
> arguments and since music expression parts must not occur more than
> once, one @emph{does} generally need to use copying operators in the
> @emph{replacement} expression @var{music} when using an argument more
> than once there. Using an argument more than once in @var{reference},
> in contrast, does not make sense.
> "
>
> ;; pitch and music generator might be stored instead in music
> ;; properties, and it might make sense to create a music type of its
> ;; own for this kind of construct rather than using
> ;; RelativeOctaveMusic
> (define ((make-relative::to-relative-callback variables music-call ref-call)
> music pitch)
> (let* ((ref-vars (map (lambda (v)
> (if (ly:pitch? v)
> (make-music 'NoteEvent 'pitch v)
> v))
> variables))
I didn't try it, though, two closing parens missing, c/p-error?
> (after-pitch (ly:make-music-relative! (apply ref-call ref-vars)
> pitch
> (actual-vars (map (lambda (v r)
> (if (ly:pitch? v)
> (ly:music-property r 'pitch)
> v))
> variables ref-vars))
> (rel-music (apply music-call actual-vars)))
> (set! (ly:music-property music 'element) rel-music)
> after-pitch))
> `(make-music 'RelativeOctaveMusic
> 'to-relative-callback
> (,make-relative::to-relative-callback
> (list ,@variables)
> (lambda ,variables ,music)
> (lambda ,variables ,reference))
> 'element ,music))
Cheers,
Harm
Re: Scheme function question, David Kastrup, 2013/11/22