Jean Abou Samra <j...@abou-samra.fr> writes: > [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.
Not particularly worrisome. > Do you have examples of that happening? "\\%" = "Huh?" x = "What?" sam = #(define-music-function (x) (string?) #{ \lyricmode { \% #x } #}) \lyrics { "Hi" \sam "Hello" } > 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. x is a valid Scheme expression here but escaped being treated as closure. >> 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.ly > Time (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.ly > Time (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. Huh? You need to set it to #t rather than remove it. > 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"). But there is a difference between variables and local bindings. This is just serving to confuse people by comingling Scheme and LilyPond in an incomprehensible manner. -- David Kastrup