[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: LilyPond to Scheme to Lilypond and variadic function
From: |
Aaron Hill |
Subject: |
Re: LilyPond to Scheme to Lilypond and variadic function |
Date: |
Tue, 24 Nov 2020 16:44:52 -0800 |
User-agent: |
Roundcube Webmail/1.4.9 |
On 2020-11-24 3:00 pm, Daniel Tomas wrote:
I am working on a Microtonal key for LilyPond, but I need help to
construct
a function which I will try to simplify here. I have some questions :
1) In Scheme can be possible to write a function which is variadic with
a
point :
( function (arg1 arg2 . m ) ( ... ))
And here m contains not only one parameter passed. m1, m2, ...
I have not found in any place information about how to access m, is it
a
list ? But in this case, we can directly use a list like
(function (arg1 arg2 ls) ( ... ))
m is a list, although there are helpers for destructuring it. This is
documented in the Guile manual [1].
[1]: https://www.gnu.org/software/guile/docs/docs-1.8/guile-ref/
%%%%
\version "2.20.0"
#(define (func first second . rest)
(let-optional rest ((third 'default) (fourth 'default))
(format #t "\n -- func --")
(format #t "\n required args: first=~s, second=~s" first second)
(format #t "\n destructured args: third=~s, fourth=~s" third fourth)
(format #t "\n additional args: rest=~s" rest)))
#(func 'a 'b)
#(func 'c 'd 'e)
#(func 'f 'g 'h 'i 'j)
%%%%
====
Parsing...
-- func --
required args: first=a, second=b
destructured args: third=default, fourth=default
additional args: rest=()
-- func --
required args: first=c, second=d
destructured args: third=e, fourth=default
additional args: rest=()
-- func --
required args: first=f, second=g
destructured args: third=h, fourth=i
additional args: rest=(j)
Success: compilation successfully completed
====
The advantage of (lambda args) over (lambda (args)) is that the list is
implicit. Callers can invoke the procedure more naturally. Imagine if
one had to say (+ (list 1 2 3)) instead of simply (+ 1 2 3).
2) Now i need to do this with music information like :
Function = #(define-music-function
(parser location cyclic ls)
(boolean? list?)
#{
...
How call to another function which arguments are musical elements and 2
numbers passed n times by <ls> ?
...
#}
)
Function need to be called with unfixed number N of arguments :
\Function #t c4 2 3 d 2 5 e 4 1 f2 1 1 ... musicN nN1 nN2
Please , somebody can help me ?
The above cannot be done as LilyPond's scheme functions cannot handle
such open-ended arity. The only variability is optional arguments, and
even then there are some restrictions due to how the parser works.
To provide arbitrary numbers of things, you must use a list of some
form.
%%%%
\version "2.20.0"
foo =
#(define-void-function (args) (list?) (format #t "\n args=~s" args))
\foo #'(this is a literal scheme list)
\foo 3,1,4,1,5,9,2,6 % ..a list of natural numbers
\foo This.Is.A.Symbol.List
baz =
#(define-void-function (prop args) (symbol? ly:music?)
(set! args (map (lambda (m) (ly:music-property m prop))
(extract-typed-music args 'rhythmic-event)))
(format #t "\n args=~s" args))
\baz pitch { c d e f }
\baz duration { 1 2. 4 }
\baz text \lyricmode { Here are some words. }
%%%%
====
Parsing...
args=(this is a literal scheme list)
args=(3 1 4 1 5 9 2 6)
args=(This Is A Symbol List)
args=(#<Pitch c > #<Pitch d > #<Pitch e > #<Pitch f >)
args=(#<Duration 1 > #<Duration 2. > #<Duration 4 >)
args=("Here" "are" "some" "words.")
Success: compilation successfully completed
====
With \foo, we are leveraging some of LilyPond's syntactic elements that
ultimately resolve to a list. There are limitations on what types of
data can appear, but it is certainly an option to consider.
\baz demonstrates working with music as a container for data. This
option is ideal when inputting a variable number of musical things as it
largely resembles other LilyPond syntax.
-- Aaron Hill