[This is the continuation of https://lists.gnu.org/archive/html/lilypond-user/2022-12/msg00321.html]
Le 30/12/2022 à 15:07, David Kastrup a écrit :
You conflate "parsing" and "reading". For #{...#}, there is a rudimentary scan for # and $
Yes, I know that.
that tends to deliver false positives (which then just don't get evaluated later on)
This sounds worrisome. Do you have examples of that happening? The Scheme reader will throw an error that is incomprehensible for the user in case this happens and # or $ is followed by something that is not a valid Scheme expression, so avoiding false positives is important for correctness.
and may get confused into overlooking actual positives. \ offers a lot more potential for getting this wrong.It would also make Guile evaluate one (lambda () <variable>) per use of \ in #{ #}, which I don't believe is costly.It is. The optimisation of not putting up closures for most constants made a relevant performance difference.
I did a test with a file constructed using $ echo '\version "2.25.1"' > perftest.ly $ for i in `seq 10000`; do echo '##{ #1 #}' >> perftest.ly; done I pinned my CPUs at 2GHz (to reduce statistical noise) and measured: $ hyperfine -m 30 'master/build/out/bin/lilypond perftest.ly' Benchmark 1: master/build/out/bin/lilypond perftest.lyTime (mean ± σ): 1.446 s ± 0.021 s [User: 1.395 s, System: 0.107 s]
Range (min … max): 1.410 s … 1.498 s 30 runs $ hyperfine -m 30 'build/out/bin/lilypond perftest.ly' Benchmark 1: build/out/bin/lilypond perftest.lyTime (mean ± σ): 1.609 s ± 0.083 s [User: 1.551 s, System: 0.108 s]
Range (min … max): 1.539 s … 1.917 s 30 runs The second one is with the removal of the (or (symbol? expr) ...) test in parser-ly-from-scheme.scm. The difference is about 0.16s for 10,000 expressions, or 16μs / expression. Next, I tried this: $ cat perftest.ly \version "2.25.1" #(define-syntax-rule (repeat n body body* ...) (let ((n* n)) (do ((i 0 (1+ i))) ((eqv? i n*)) body body* ...))) #(repeat 10000 #{ #1 #}) Result: $ hyperfine -m 30 -i 'master/build/out/bin/lilypond perftest.ly' Benchmark 1: master/build/out/bin/lilypond perftest.lyTime (mean ± σ): 840.7 ms ± 7.9 ms [User: 793.3 ms, System: 96.9 ms]
Range (min … max): 825.1 ms … 859.3 ms 30 runs $ hyperfine -m 30 -i 'build/out/bin/lilypond perftest.ly' Benchmark 1: build/out/bin/lilypond perftest.lyTime (mean ± σ): 822.7 ms ± 13.0 ms [User: 779.4 ms, System: 98.8 ms]
Range (min … max): 803.9 ms … 855.5 ms 30 runs The main difference is that this one executes the reader logic only once, but evaluates the resulting #{ #} expression many times (which is closer to what happens with music functions). This one actually turns out faster without the optimization. It could be due to the fact that a closure makes parse-scm.cc bail out before looking up 'compile-scheme-code in the Scheme option hash table, or to scm_primitive_eval (constant) being a little slower than ly_call (lambda_returning_constant). At any rate, the difference is ~2μs / evaluation.
And there is absolutely no associated gain at all since $identifier will work just fine where scoping is needed. The gain of "people using Scheme but not understanding it might by chance escape trivial errors" is not really a gamechanger.
The Notation manual has a section on what it calls "substitution functions", which is separate from the section on music functions in the Extending manual, and I think that is for good reason. Those "substitution functions" have the form of a define-music-function where the body is just a #{ ... #}. There is little Scheme "programming" involved for that apart from cargo-cult copy&pasting of the define-music-function template and picking type predicates from the list in the documentation. I regularly see people (especially on lilypond-user-fr lately) wondering why returning #{ \book { ... } #} from a music function does not work, and that sort of thing. It's LilyPond's kind of "macro" facility, which is accessible to all users including those who know nothing about Scheme, and I think there is a point in making it behave more like users would expect ("just use variables like you always do, except that the variables change every time"). Jean
OpenPGP_signature
Description: OpenPGP digital signature