On 2018-05-11 23:01, David Kastrup wrote:
The reason why #{ $p #} does not work as the body of a music function
is that it will only evaluate to a pitch not a note, and that pitch by
itself is not enough to create a music expression.
Wrong again. There is no such thing as a "pitch by itself" in Scheme.
A pitch is not a deficient music expression, rather it is not a music
expression at all. It's like saying a character by itself is not
enough
to create a string, as if two characters by itself would create a
string. Strings are not the same as characters of any count.
Strings are a separate data structure from characters. You can place
characters in other data structures. You can certainly also form
one-character strings.
(make-music 'NoteEvent 'pitch #{ c' #})
is a music expression a music function can return (it's deficient for a
number of unchanged uses in that it is lacking a duration but you can
add durations afterwards if you want to with different music
functions).
Two pitches are not enough to create a music expression. Ten pitches
aren't. If you want to create a music expression, you need to create a
music expression, like using make-music. Or use some #{ ... #}
construct recognized as producing music.
#{ $p 4 #} works because a pitch followed by a duration clearly
defines a note, which is enough to form a music expression.
#{ $p #} #{ 4 #} is a pitch followed by a duration and does not form a
music expression. The music expression is created by specific forms of
the #{ ... #} syntax.
Okay, then none of this makes any logical sense.
It is my understanding that #{ #} is an escaping mechanism. Its purpose
is to facilitate mixing LilyPond syntax within a Scheme construct. At
the end of the day, everything that is input to the LilyPond program
becomes one long Scheme expression. LilyPond syntax is essentially
nothing more than a convenient abbreviation for equivalent Scheme.
To that end, there is a parser involved in processing LilyPond syntax to
generate the desired Scheme expressions. It sounded like the underlying
issue with the original poster's error was that of a limitation during
parsing. To simply include "c'" by itself within #{ #} causes the
parser to only generate enough Scheme for the specified NOTENAME_PITCH
token which would be an ly:pitch. This looked to me to be similar to
when you only include "c'" by itself in a LilyPond file and try to
compile it. You minimally need to enclose it in braces to give the
parser some context. As such, that is why I offered a solution of #{ {
$p } #}, since that successfully gets around the error.
Of course, I tried something just now that I should have tried before.
That is, what happens with a file containing only "c' d'"? Oh, well, it
fails to compile as well. Crud. So my conclusion that the parser in
general is able to figure out what is meant by a sequence of bare
pitches is wrong. The parser really does need more context to make
sense of things. However, that does not immediately explain why #{ c'
d' #} works. It would seem that it should fail for similar reasons.
There is clearly magic in #{ #} that is non-obvious here. But why is
its behavior inconsistent? Surely if #{ c' d' #} is "smart" enough to
interpret two bare pitches as a sequence of notes with assumed
durations, why can it not do the same for a single pitch. Or, said
another way, HOW does one actually make #{ $p #} work for a music
function? Certainly, #{ { $p } #} and #{ <> $p #} both appear to work
for producing music with the pitch as a note, and you provided a way to
verbosely use make-music for the task. Is there no other way to force
#{ #} to interpret its contents as producing music?
At this point, I must confess that I tell a lie. To say this makes no
logical sense was hyperbolic. Is this not, as I have tried and failed
to relay, simply an issue of mismatched types? #{ $p #} results in a
pitch not music. That is why it cannot be the sole body of a music
function. Music functions must return music, and #{ #} will never
evaluate to music if provided a bare pitch as input. You are left with
an ly:pitch that needs extra work to become music.
If so, that actually does make sense. It would be madness if #{ #}
always tried to form a music expression with whatever you gave it, since
that would give you no way of easily expressing the myriad of other
syntactic element types within Scheme. Your explicit make-music example
for instance must rely on #{ c' #} evaluating only to a pitch for the
purposes of defining the NoteEvent.
Now, #{ c' d' #} could be interpreted in one of two ways. Is this a
list of two pitches, or is this a music expression formed by two notes
without explicit durations? The latter seems to be the more common use
case, so understandably that is what happens. And right there is the
magic. The parser normally would not accept two bare pitches as music;
but within the #{ #} construct it does consider that as sufficient to
produce music.
This would run counter to your assertion that "[two] pitches are not
enough to create a music expression." Outside of the #{ #} construct,
yes, that appears to be the case. A LilyPond file with just "a b c"
will not work, and I was wrong if I implied that in my post. However,
this discussion is about the #{ #} construct. And within the #{ #}
construct, the parser, it would seem, follows different rules allowing
#{ a b c #} to produce music but not #{ a #}.
Something like #{ a #} #{ 2 #} is an entirely different scenario
altogether. <insert "Airplane" reference here> As you have introduced
a second #{ #} construct, it should be no surprise the parser will treat
each construct individually. As neither ly:pitch nor ly:duration is
valid to return from a music function, define-music-function is unhappy.
And this would disagree with your comment that "There is no such thing
as a 'pitch by itself' in Scheme.". There very much is such a thing as
a pitch in Scheme. The type ly:pitch alone is evidence of that,
otherwise the premise of the original poster's music function is flawed.
Perhaps what you intended to stress is that a music expression within
Scheme cannot consist of a pitch (or duration) by itself. Let's pretend
for a moment that #{ a #} and #{ 2 #} could evaluate to music. They
would each end up defining a NoteEvent. The ly:pitch and ly:duration
values would be properties of their respective events and therefore
would not be standing alone within the expression.
But this all reinforces the crux of the confusion: that #{ #} sometimes
evaluates to music and sometimes does not. While this behavior can be
helpful, surely it must be the entire reason why the original poster's
function does not work as intended.
-- Aaron Hill
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user