[Top][All Lists]

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

summary: lilypond, lambda, and local-eval

From: Andy Wingo
Subject: summary: lilypond, lambda, and local-eval
Date: Thu, 15 Dec 2011 11:21:18 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux)


The "delayed evaluation" thread is a bit long and confusing, so I would
like to try to summarize it.

Lilypond has a way to embed Lilypond code in Scheme, and Scheme code in
Lilypond code.  The former uses a reader macro, #{#}.  The latter uses
specially-marked variables and expressions, specifically, those preceded
by $ or #.

For example, the following Scheme expression is an embedded lilypond
code fragment:

    #{ \displayLilyMusic $p #}

which expands out at read-time to:

    (#<procedure embedded-lilypond (parser lily-string filename line closures)>
     " \\displayLilyMusic $p "
     (list (cons 20 (lambda () p))))

Here the procedure is embedded in the output of the reader macro.  We
can see that the $p is translated to (cons 20 (lambda () p)).  Whenever
$p is evaluated, that lambda is run.

Embedded Scheme (via $ or #) has access to Scheme's environment.
Variables in lilypond are in a separate environment (implemented using
modules), so we don't have to be concerned about lilypond accessing or
defining Scheme lexicals.

David hacks on Lilypond.  He notes that the above expression used to
expand out to:

    (#<procedure embedded-lilypond (parser lily-string filename line closures)>
     " \\displayLilyMusic $p "

in 1.8.  Then, whenever lilypond needed to evaluate an embedded Scheme
value, it would use `local-eval' with the captured environment.  It is
clearly much more convenient for lilypond hackers than having to scan
for embedded Scheme beforehand and build up closures for each embedded
Scheme expression.  David noted that while "the closure solution" works
for him, he wondered if there was something better to use.

It took some time for everyone to understand the problem.  In the end,
there were four workable possibilities.

  1) Keep using closures.

  2) Incorporate local-eval and the-environment into Guile 2.0.

  3) Have lilypond use its own evaluator or compiler.

  4) Have lilypond make the embedded lilypond code expand out to actual
     Scheme.  (It was unclear whether the lilypond grammar allowed

Mark and Noah looked at implementing local-eval, and I recommended
staying with the closure solution.  Ludovic noted success with method
(3) in the Skribilo context.

I would like to start a new thread around local-eval, but besides that,
we should probably agree on the summary first.  So please do send any
corrections to this summary to the list.  Thanks :)


reply via email to

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