2018-03-01 18:31 GMT+01:00 Stefano Troncaro <stefanotronc...@gmail.com>: > I didn't know about \default or the dot/comma separated number/symbol lists! > I can see those being useful in some circumstances. I was thinking about > cases where an undefined amount of things different than symbols or numbers > are required, and the closest I can imagine is chaining functions to create > the illusion of a variable amount of arguments, like this: >> >> \version "2.19.80" >> >> #(define (end-list? obj) >> (and (list? obj) >> (let ((item (last obj))) >> (and (symbol? item) >> (equal? "end" (symbol->string item)))))) >> >> end = #(list 'end) >> >> #(define (el->curated-el el) >> (delete 'end el)) >> >> untilEnd = >> #(define-void-function (proc el) (procedure? end-list?) >> (let ((curated-el (el->curated-el el))) >> (for-each >> (lambda (elem) >> (proc elem)) >> curated-el))) >> >> selfAppending = >> #(define-scheme-function (e-l) (end-list?) >> (let ((self-input (list (cons 1 2) (cons 3 4)))) >> (append self-input e-l))) >> >> selfAppendingInput = >> #(define-scheme-function (input e-l) (scheme? end-list?) >> (append (list input) e-l)) >> >> \relative c'' { >> c d e f >> \untilEnd #pretty-print >> \selfAppending >> \selfAppendingInput #'(some useful input?) >> \selfAppendingInput #selfAppending >> \selfAppending >> \end >> g a b c >> } > > This structure just happens to work for something I'm trying now but I can > see it being too narrow in general. > > @Urs, I not familiar with \with blocks, I'll take a look at the oll-core > code and experiment a bit with it. Maybe I'll be able to help. > > 2018-03-01 4:55 GMT-03:00 David Kastrup <d...@gnu.org>: >> >> Stefano Troncaro <stefanotronc...@gmail.com> writes: >> >> > Thank you! I see that this is not an option then. Also, I now understand >> > why I couldn't make the optional arguments work, since I always left >> > them >> > for last. >> > >> > Do you know if it is possible to have a flexible amount of optional >> > arguments that appear before the last mandatory one? Say, for example >> > (define-music-function (arg1 args music) (number? ??? ly:music?) where >> > arg1 >> > and music are mandatory, and basically everything between arg1 and the >> > next >> > music expression is compacted into a list and accessed as args in the >> > body >> > of the function. Not with that syntax necessarily, but something that >> > allows for that kind of usage? >> >> You know that a number or symbol list can be entered as a >> comma-separated list? >> >> -- >> David Kastrup
Hi Stefano, I was always fine with one optional list?-predicate (this may ofcourse be an alist) and sorting/processing this list in the body of the music-function. Or things like (lambda (arg . rest) ...) in some cases or the comma-separated list (as already mentioned). If you really want to go for a music-function with arbitrary arguments here some thoughts. Beside the result has still limitations: - the amount of possible arguments has to be specified (ofcourse you can go for something like 20, which should really be enough (currently 5 are defined) - all those arguments have to be of kind (not (ly:music ...)), which makes it impossible to enter a second music-argument. - maybe more, it's not tested beyond the given examples I expect David K will point out more weaknesses ... lol I deleted the not matching doc-strings from define-syntax-function and define-music-function. Look into music-functions.scm to read them. \version "2.19.65" #(defmacro-public define-my-syntax-function (args-amount type args signature . body) (define (has-parser/location? arg where) (let loop ((arg arg)) (if (list? arg) (any loop arg) (memq arg where)))) (define (currying-lambda args doc-string? body) (if (and (pair? args) (pair? (car args))) (currying-lambda (car args) doc-string? `((lambda ,(cdr args) ,@body))) (let* ((compatibility? (if (list? args) (= (length args) (+ 2 (length signature))) (and (pair? args) (pair? (cdr args)) (eq? (car args) 'parser)))) (realargs (if compatibility? (cddr args) args))) `(lambda ,realargs ,(format #f "~a\n~a" realargs (or doc-string? "")) ,@(if (and compatibility? (has-parser/location? body (take args 2))) `((let ((,(car args) (*parser*)) (,(cadr args) (*location*))) ,@body)) body))))) (let ((docstring (and (pair? body) (pair? (cdr body)) (if (string? (car body)) (car body) (and (pair? (car body)) (eq? '_i (caar body)) (pair? (cdar body)) (string? (cadar body)) (null? (cddar body)) (cadar body)))))) (let ((new-args (map (lambda (i) (string->symbol (format #f "~a-~a" (car args) i))) (iota args-amount 1 1)))) (set! args (append new-args (cdr args))) (set! signature (append (make-list args-amount (car signature)) (cdr signature)))) ;; When the music function definition contains an i10n doc string, ;; (_i "doc string"), keep the literal string only `(ly:make-music-function (list ,@(map (lambda (pred) (if (pair? pred) `(cons ,(car pred) ,(and (pair? (cdr pred)) (cadr pred))) pred)) (cons type signature))) ,(currying-lambda args docstring (if docstring (cdr body) body))))) #(defmacro-public define-my-music-function rest `(define-my-syntax-function ,(car rest) (ly:music? (make-music 'Music 'void #t)) ,@(cdr rest))) tst = #(define-my-music-function 5 (xy mus) (((lambda (x) (not (ly:music? x))) #f) ly:music?) "DOCME" (format #t "\n\tTHIS IS EXPERIMANTAL CODE. DON'T USE IT FOR SERIOUS WORK\n\n") (pretty-print (list xy-1 xy-2 xy-3 xy-4 xy-5)) (if (number-pair? xy-2) #{ \once \override Rest.extra-offset = #xy-2 $mus #} #{ #})) { \tst r4 r2 r4 } { \tst #'a r4 r2 r4 } { \tst #'a #(cons 1 2) r4 r2 r4 } { \tst #'a #(cons 1 2) #'(cons 3 4) r4 r2 r4 } { \tst #'a #(cons 1 2) #'(cons 3 4) #'(some useful input?) r4 r2 r4 } { \tst #'a #(cons 1 2) #'(cons 3 4) #'(some useful input?) #"foo" r4 r2 r4 } Cheers, Harm _______________________________________________ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user