Valentin Villenave <valen...@villenave.net> writes: > On Fri, Dec 2, 2011 at 1:59 PM, David Kastrup <d...@gnu.org> wrote: >> I don't see why defmacro should have ceased working, so it might be >> worth revisiting the problems you experienced. > > It's not defmacro that ceased working, it's just that I previously > used the old ly:make-music-function syntax, which you changed when > making music-functions optargs-able: > > #(use-modules (srfi srfi-39)) > > #(define-public *tuplet-letter* (make-parameter "t")) > > #(defmacro make-simple-function (token expr) > (let* ((sym (string->symbol (primitive-eval token)))) > `(define-public ,sym > (ly:make-music-function (list ly:music?) > (lambda (parser location x) > ,expr))))) > > #(make-simple-function (*tuplet-letter*) #{ \times 2/3 $x #} ) > > > { \t { a b c } }
Apart from the rest of this ugly contraption, there is no reason whatsoever why you are calling the _internals_ of making music functions here instead of define-music-function itself. #(defmacro make-simple-function (token expr) (let* ((sym (string->symbol (primitive-eval token)))) `(define-public ,sym (define-music-function (parser location x) (ly:music?) ,expr)))) Yes, I changed the internals because the internals needed more information. But the user API remained identical, and I don't understand why you don't use it. It's not like things get simpler when you sidestep the documented API. If you insist on meddling with _internals_ of Lilypond for no discernible reason, yes, you have to expect breakage from time to time. And there will be no convert-rules helping the upgrade. > This is a case where eval-string can be used (I'm not suggesting it's > proper coding practice, though -- in fact *even I* can see how ugly it > is): > > #(use-modules (srfi srfi-39)) > > #(define-public *tuplet-letter* (make-parameter "t")) > > #(define-public (make-simple-function token expr) > (eval-string (format #f > "(define-public ~a > (define-music-function (parser location x) (ly:music?) ~a ))" > token expr))) > > #(make-simple-function (*tuplet-letter*) "#{ \\times 2/3 $x #}" ) > > { \t { a b c } } This is ridiculous. Now you use the API. What makes you think eval-string is necessary for using define-music-function? > BTW, could you explain again why in the following example the variable > is overriden with # but not with $? I thought $ gave us the "old" > instant-evaluation behavior, but here it doesn't seem to be evaluated > before the music is parsed: > > myvar = { b'4 } > > $(display "this shouldn't be needed anyway") > $(eval-string "(define-public myvar #{ a'2 #} )" ) > > \new Staff \myvar You need #(display ...). $ takes a look at the type of the enclosed expression and creates a token of the appropriate type in the input stream. The type of the enclosed expression is *unspecified* so nothing gets inserted into the input stream by the lexer and the parser is completely unimpressed. With #(display ..., the resulting token type is a Scheme token. The parser throws it away in this context, but it knows that a Scheme token can't be between { b'4 } and \addlyrics (for example). So the rule it exercises for throwing the Scheme token away makes sure that the next token is not needed as lookahead token for finishing the previous token. You can't write #(display ... in any context, only where Scheme tokens are allowed. $(display ... in contrast is allowed anywhere since the parser never gets to see anything. Since the parser does not get to see anything, it does not change parsing. -- David Kastrup _______________________________________________ bug-lilypond mailing list bug-lilypond@gnu.org https://lists.gnu.org/mailman/listinfo/bug-lilypond