Discussion:
simple scheme in lilypond
Gianmaria Lari
2018-11-27 08:14:35 UTC
Permalink
Probably these are very trivial things. Sorry to ask them but would like to
understand.

If I write (1):


\version "2.19.82"
$(object->string (+ 3 2))


Lilypond is happy and compile to a pdf file showing "5".

Even this simpler code works... (2)

\version "2.19.82"
$"Hello"


and generate a pdf file showing "Hello".

It is clear to me that $ introduce a scheme expression that is evaluated.
And in the previous two examples the scheme code is evaluated to strings.
But I don't understand why lilypond outputs them. If I write (3):

\version "2.19.82"
"Test"


this does not compile. So I would think that the "correct" code to output
evaluated expression in the pdf file should be (4)


\version "2.19.82"
\markup $(object->string (+ 3 2))


or this (5)

\version "2.19.82"
\markup $"Hello"


Why the behaviour of (1) and (2) ?

* * *

I tried to rewrite (1) and (2) with the hash mark instead of dollar (6):

\version "2.19.82"
#(object->string (+ 3 2))


and (7):

\version "2.19.82"
#"Hello"


This time, there is no output in the pdf file. Why this difference?

Thank you, g.
Jan-Peter Voigt
2018-11-27 10:47:46 UTC
Permalink
Hello,

the $ sign has a special meaning of "instant scheme-expression". An
instant scheme expression is evaluated instantly *and* the result is
observed so that lilypond can decide what to do with it. When lily
receives something that can be treated as a markup from an instant
scheme expression it is handled like \markup {}. But a pure string is
not a core lily-expression like music or markup. Thats the reason (3)
fails with an error. The result of a plain scheme-exression introduced
with # is simply ignored in root context.

HTH
Jan-Peter
Post by Gianmaria Lari
Probably these are very trivial things. Sorry to ask them but would like
to understand.
\version "2.19.82"
$(object->string (+ 3 2))
Lilypond is happy and compile to a pdf file showing "5".
Even this simpler code works... (2)
\version "2.19.82"
$"Hello"
and generate a pdf file showing "Hello".
It is clear to me that $ introduce a scheme expression that is
evaluated. And in the previous two examples the scheme code is evaluated
to strings. But I don't understand why lilypond outputs them. If I write
\version "2.19.82"  
"Test"
this does not compile. So I would think that the "correct" code to
output evaluated expression in the pdf file should be (4)
\version "2.19.82"
\markup $(object->string (+ 3 2))
or this (5)
\version "2.19.82"
\markup $"Hello"
Why the behaviour of (1) and (2) ?
* * *
\version "2.19.82"
#(object->string (+ 3 2))
\version "2.19.82"
#"Hello"
This time, there is no output in the pdf file. Why this difference?
Thank you, g.
_______________________________________________
lilypond-user mailing list
https://lists.gnu.org/mailman/listinfo/lilypond-user
Gianmaria Lari
2018-11-28 07:47:41 UTC
Permalink
Thank you Jan, very clear.
g.
Post by Jan-Peter Voigt
Hello,
the $ sign has a special meaning of "instant scheme-expression". An
instant scheme expression is evaluated instantly *and* the result is
observed so that lilypond can decide what to do with it. When lily
receives something that can be treated as a markup from an instant
scheme expression it is handled like \markup {}. But a pure string is
not a core lily-expression like music or markup. Thats the reason (3)
fails with an error. The result of a plain scheme-exression introduced
with # is simply ignored in root context.
HTH
Jan-Peter
Post by Gianmaria Lari
Probably these are very trivial things. Sorry to ask them but would like
to understand.
\version "2.19.82"
$(object->string (+ 3 2))
Lilypond is happy and compile to a pdf file showing "5".
Even this simpler code works... (2)
\version "2.19.82"
$"Hello"
and generate a pdf file showing "Hello".
It is clear to me that $ introduce a scheme expression that is
evaluated. And in the previous two examples the scheme code is evaluated
to strings. But I don't understand why lilypond outputs them. If I write
\version "2.19.82"
"Test"
this does not compile. So I would think that the "correct" code to
output evaluated expression in the pdf file should be (4)
\version "2.19.82"
\markup $(object->string (+ 3 2))
or this (5)
\version "2.19.82"
\markup $"Hello"
Why the behaviour of (1) and (2) ?
* * *
\version "2.19.82"
#(object->string (+ 3 2))
\version "2.19.82"
#"Hello"
This time, there is no output in the pdf file. Why this difference?
Thank you, g.
_______________________________________________
lilypond-user mailing list
https://lists.gnu.org/mailman/listinfo/lilypond-user
_______________________________________________
lilypond-user mailing list
https://lists.gnu.org/mailman/listinfo/lilypond-user
David Kastrup
2018-11-27 11:11:47 UTC
Permalink
Post by Gianmaria Lari
Probably these are very trivial things. Sorry to ask them but would like to
understand.
\version "2.19.82"
$(object->string (+ 3 2))
Lilypond is happy and compile to a pdf file showing "5".
Even this simpler code works... (2)
\version "2.19.82"
$"Hello"
and generate a pdf file showing "Hello".
It is clear to me that $ introduce a scheme expression that is evaluated.
And in the previous two examples the scheme code is evaluated to strings.
\version "2.19.82"
"Test"
blabla = "Test"
##f
\blabla

will compile again (sorry for the ##f : it is necessary to defeat
lookahead). It is indistinguishable from

blabla = \markup "Test"
##f
\blabla

in output and in its effect on the variable. Basically, $x and \x are
the same (apart from the characters allowed in and after x). The
logical thing would be to permit "Test" on its own but it appears rather
error-prone. This is similar to

blabla = c4
##f
\blabla

compiling and producing a result while

c4

on its own doesn't.
Post by Gianmaria Lari
\version "2.19.82"
#(object->string (+ 3 2))
\version "2.19.82"
#"Hello"
This time, there is no output in the pdf file. Why this difference?
At the top level of the file, assignments and assignment-like statements
may be executed. The return value of an assignment in Scheme is
unspecified. There are things like

#(set! (hashq-ref x y) z)

that somewhat inscrutably return an actual value other than
*unspecified*. For that reason, # expressions in contexts where
assignments are allowed are evaluated and ignored. Use $ if you want
them to be heeded.
--
David Kastrup
Gianmaria Lari
2018-11-28 08:11:56 UTC
Permalink
Post by David Kastrup
Post by Gianmaria Lari
Probably these are very trivial things. Sorry to ask them but would like
to
Post by Gianmaria Lari
understand.
\version "2.19.82"
$(object->string (+ 3 2))
Lilypond is happy and compile to a pdf file showing "5".
Even this simpler code works... (2)
\version "2.19.82"
$"Hello"
and generate a pdf file showing "Hello".
It is clear to me that $ introduce a scheme expression that is evaluated.
And in the previous two examples the scheme code is evaluated to strings.
\version "2.19.82"
"Test"
blabla = "Test"
##f
\blabla
will compile again (sorry for the ##f : it is necessary to defeat
lookahead). It is indistinguishable from
blabla = \markup "Test"
##f
\blabla
in output and in its effect on the variable. Basically, $x and \x are
the same (apart from the characters allowed in and after x). The
logical thing would be to permit "Test" on its own but it appears rather
error-prone.
"... but it appears rather error prone" then lilypond forbid it. Is that
right?
Wouldn't be better just a warning like when you make an assignment inside a
conditional statement?

Thank you, g.
David Kastrup
2018-11-28 09:47:03 UTC
Permalink
Post by Gianmaria Lari
Post by David Kastrup
in output and in its effect on the variable. Basically, $x and \x are
the same (apart from the characters allowed in and after x). The
logical thing would be to permit "Test" on its own but it appears rather
error-prone.
"... but it appears rather error prone" then lilypond forbid it. Is that
right?
Wouldn't be better just a warning like when you make an assignment inside a
conditional statement?
C++ has been designed to be readable to the computer, LilyPond has been
designed to be readable to the user. A standard compliant compiler is
not allowed to throw errors for things permitted by the standard even if
they are a bad idea. If there is no conceivable reason to be writing
things in an unreadable manner, LilyPond not rarely makes the choice
just not to permit them. For example, what do we gain when we allow

c4 d e c g g c1

to be valid input creating 7 single-note scores one after another?
Consistency, because you can do the same by passing each note through a
music variable. But if the user actually meant what he stated here, it
would have been easy to explicitly write something like

{ c4 } { d } { e } { c } { g } { g } { c1 }

Now with regard to quoted strings, they can also be used for creating
identifiers. I can write

"Test" = 7

and that is not supposed to typeset "Test" but assign to a variable
called "Test".

It does not particularly help that something like cis=4 is valid note
input (a quarter note with an octave check to the small octave). Giving
"Test" specific meaning when not followed by = requires lookahead.
Lookahead always is good for trouble. We may already have it here for
unrelated reasons: not sure. Either way, when the compiler requires
lookahead to figure out things, so does the human reader. The language
becomes harder to understand.

Now where "Test" is supposed to be interpreted as a string, it would
seem surprising that #"Test" in the same location would be ignored and I
already explained the rationale for ignoring #-expressions in places
where assignments are allowed.

Basically you are asking to open a can of worms here not because you
actually want a worm but because you consider closed cans offensive.

In this case, if you go to lily/parser.yy and add the production
STRING | to the front of the definition of toplevel_expression (you'd
also need to add an action, namely the relevant part of the preexisting
action for embedded_scm_active), you can then do

bison -rall -g lily/parser.yy

and check the warnings and log files for conflicts (in this case
actually none). That often is enough to see why a particular proposal
is a bad idea even if it does indeed not trigger on this particular one.

So when messing with syntax in areas that are already pretty full always
triggers the "what is this actually good for?" question and I haven't
seen an answer so far that would convince me we are doing anybody much
of a favor by filling this in the manner you want.
--
David Kastrup
Loading...