lilypond-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A question about a scheme function with two input notes


From: David Kastrup
Subject: Re: A question about a scheme function with two input notes
Date: Sat, 31 Dec 2022 03:47:11 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux)

Jean Abou Samra <jean@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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]