Weird intermediate context creation

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Weird intermediate context creation

Dan Eble
I find it strange that this code in input/regression/bend-bound.ly ends up on two staves rather than one:

music = \repeat unfold 16 { c''4\bendAfter #-4 }
sixteens = \repeat unfold 64 { c'16 }

\new Score {
  << \music \sixteens >>
}

I have a pretty good idea of why it is happening, and I am currently testing a change that affects 4 layout regtests including this one.

The question is whether changing it is the right thing to do.  On the one hand,

the current result is strange
the NR is not clear as to whether the current result is expected; I lean toward reading it as unexpected
the NR advises against relying on implicit context creation anyway

NR section 5.1.2 begins,

LilyPond will create lower-level contexts automatically if a music expression is encountered before a suitable context exists, but this is usually successful only for simple scores or music fragments like the ones in the documentation.

The NR defines "bottom-level contexts" to include Voice and to exclude Staff, but leaves the reader to draw his own conclusion of what  "lower-level contexts" are.  I guess it means any required contexts that don't yet exist.

I'm not sure from this whether to expect \music and \sixteens to end up in separate Voice contexts.  My intuition is that after a Voice context is created for \music, "a suitable context exists" for \sixteens.

On the other hand, changing this would change how existing scores that rely on automatic context creation are engraved.  Is a change justified either on the grounds that the current behavior is a bug or that the NR gives fair warning not to rely on this feature?

Dan

dak
Reply | Threaded
Open this post in threaded view
|

Re: Weird intermediate context creation

dak
Dan Eble <[hidden email]> writes:

> I find it strange that this code in input/regression/bend-bound.ly
> ends up on two staves rather than one:
>
> music = \repeat unfold 16 { c''4\bendAfter #-4 }
> sixteens = \repeat unfold 64 { c'16 }
>
> \new Score {
>   << \music \sixteens >>
> }
>
> I have a pretty good idea of why it is happening, and I am currently
> testing a change that affects 4 layout regtests including this one.

Why wouldn't it end up on two staves?  << >> does not start new
contexts, it just groups them.

\new Score {
  << { c'4 d' e' f' } { c' d' e' f' } >>
}

will also produce two staves.

> The question is whether changing it is the right thing to do.

I have no idea what you want to change it to without breaking stuff like
\new StaffGroup << ... >>

> On the one hand,
>
> the current result is strange

Can you explain why you feel that?

> the NR is not clear as to whether the current result is expected; I
> lean toward reading it as unexpected
> the NR advises against relying on implicit context creation anyway

Implicit context creation is not going away.  Things like Global and
Score context are created implicitly all the time.

> LilyPond will create lower-level contexts automatically if a music
> expression is encountered before a suitable context exists, but this
> is usually successful only for simple scores or music fragments like
> the ones in the documentation.
>
> The NR defines "bottom-level contexts" to include Voice and to exclude
> Staff, but leaves the reader to draw his own conclusion of what
> "lower-level contexts" are.  I guess it means any required contexts
> that don't yet exist.

Bottom is any context without \defaultchild .  Bottom is needed for most
events, but sets/overrides/applycontexts tend to be delivered to
somewhere in the context hierarchy.

> I'm not sure from this whether to expect \music and \sixteens to end
> up in separate Voice contexts.  My intuition is that after a Voice
> context is created for \music, "a suitable context exists" for
> \sixteens.

The items in << >> do not invade one another automatically.  You can
wrote \context Voice ... to pick up explicitly (and that's basically
what overrides/sets do) but other than that, there is no automatism.  If
I write

<< \new Staff { c' } \new Voice { d' } >>

should the d' insinuate itself into the same staff as the c' ?

> On the other hand, changing this would change how existing scores that
> rely on automatic context creation are engraved.  Is a change
> justified either on the grounds that the current behavior is a bug or
> that the NR gives fair warning not to rely on this feature?

I have no idea what behavior you propose instead.

--
David Kastrup

Reply | Threaded
Open this post in threaded view
|

Re: Weird intermediate context creation

Dan Eble
On Jan 6, 2020, at 10:57, David Kastrup <[hidden email]> wrote:
>> the current result is strange
>
> Can you explain why you feel that?

I find it strange that this music produces these diverse results:

music = << c' e' >>

\new Score { % Case A: two notes in one voice
  \new Voice \music
}

\new Score { % Case B: two voices in one staff
  \new Staff \music
}

\new Score { % Case C: two staves
  \new StaffGroup \music
}

\new Score { % Case D: two staves
  \music
}

With my experimental changes, cases B, C, and D are rendered as two voices in one staff.  They are not rendered like case A (I believe) because I haven't touched the code that makes LilyPond create a new bottom context per item in \music.

> Implicit context creation is not going away.  Things like Global and
> Score context are created implicitly all the time.

I don't propose eliminating it.  Actually, I'm experimenting with generalizing some special handling of Score.  When LilyPond creates the implied intermediate contexts required for a new context, the current behavior is to avoid creating a new Score context if one already exists.  The question I asked myself is "What if LilyPond did the same for other intermediate contexts?"  Then I tried it and discovered the impact on the bend-bound test and some others.

> If I write
>
> << \new Staff { c' } \new Voice { d' } >>
>
> should the d' insinuate itself into the same staff as the c' ?

You didn't specify a staff for the d', so I don't see grounds for dissatisfaction if LilyPond were to do that.  Having said that, my work in progress produces the same output as master for this case, so it might not be something we need to debate.  I don't understand why yet, and I ought to, so thanks for this case.

Regards,

Dan


dak
Reply | Threaded
Open this post in threaded view
|

Re: Weird intermediate context creation

dak
Dan Eble <[hidden email]> writes:

> On Jan 6, 2020, at 10:57, David Kastrup <[hidden email]> wrote:
>>> the current result is strange
>>
>> Can you explain why you feel that?
>
> I find it strange that this music produces these diverse results:
>
> music = << c' e' >>
>
> \new Score { % Case A: two notes in one voice
>   \new Voice \music
> }
>
> \new Score { % Case B: two voices in one staff
>   \new Staff \music
> }
>
> \new Score { % Case C: two staves
>   \new StaffGroup \music
> }
>
> \new Score { % Case D: two staves
>   \music
> }
>
> With my experimental changes, cases B, C, and D are rendered as two
> voices in one staff.  They are not rendered like case A (I believe)
> because I haven't touched the code that makes LilyPond create a new
> bottom context per item in \music.

At the current point of time, << ... >> is the way to create music that
will not cause a prioritised context to stick around indefinitely.

>> Implicit context creation is not going away.  Things like Global and
>> Score context are created implicitly all the time.
>
> I don't propose eliminating it.  Actually, I'm experimenting with
> generalizing some special handling of Score.  When LilyPond creates
> the implied intermediate contexts required for a new context, the
> current behavior is to avoid creating a new Score context if one
> already exists.  The question I asked myself is "What if LilyPond did
> the same for other intermediate contexts?"  Then I tried it and
> discovered the impact on the bend-bound test and some others.
>
>> If I write
>>
>> << \new Staff { c' } \new Voice { d' } >>
>>
>> should the d' insinuate itself into the same staff as the c' ?
>
> You didn't specify a staff for the d', so I don't see grounds for
> dissatisfaction if LilyPond were to do that.

It's the same as

<< \new StaffGroup { c' } \new Staff { d' } >>

where it clearly seems inappropriate to make the Staff be a part of the
StaffGroup .  I also suspect that your changes might take issue 34 to a
new level.  Not more than a hunch but this is not a simple area without
consequences and repercussions.

There's been some definition of the \after music function around and its
latest iterations contained an "artificial" simultaneous music
expression for "reasons", namely avoiding a persistent context like
described above.

> Having said that, my work in progress produces the same output as
> master for this case, so it might not be something we need to debate.
> I don't understand why yet, and I ought to, so thanks for this case.

--
David Kastrup

Reply | Threaded
Open this post in threaded view
|

Re: Weird intermediate context creation

Dan Eble
On Jan 6, 2020, at 17:01, David Kastrup <[hidden email]> wrote:

>
>>> If I write
>>>
>>> << \new Staff { c' } \new Voice { d' } >>
>>>
>>> should the d' insinuate itself into the same staff as the c' ?
>>
>> You didn't specify a staff for the d', so I don't see grounds for
>> dissatisfaction if LilyPond were to do that.
>
> It's the same as
>
> << \new StaffGroup { c' } \new Staff { d' } >>
>
> where it clearly seems inappropriate to make the Staff be a part of the
> StaffGroup.

The context schema makes these cases different.

In the new-Voice case, the Score does not accept the Voice directly.  A Staff is required between the Staff and the Voice, so the question "Which Staff?" arises.

In the new-Staff case, the Score accepts the Staff.  Placing it in a StaffGroup is not considered.

(Thanks for the rest of your reply too; I haven't digested it all yet.)

Dan


Reply | Threaded
Open this post in threaded view
|

Re: Weird intermediate context creation

Dan Eble
On Jan 7, 2020, at 09:26, Dan Eble <[hidden email]> wrote:

>
> On Jan 6, 2020, at 17:01, David Kastrup <[hidden email]> wrote:
>>
>>>> If I write
>>>>
>>>> << \new Staff { c' } \new Voice { d' } >>
>>>>
>>>> should the d' insinuate itself into the same staff as the c' ?
>>>
>>> You didn't specify a staff for the d', so I don't see grounds for
>>> dissatisfaction if LilyPond were to do that.
>>
>> It's the same as
>>
>> << \new StaffGroup { c' } \new Staff { d' } >>
>>
>> where it clearly seems inappropriate to make the Staff be a part of the
>> StaffGroup.
>
> The context schema makes these cases different.
>
> In the new-Voice case, the Score does not accept the Voice directly.  A Staff is required between the Staff and the Voice, so the question "Which Staff?" arises.

Oops: "A Staff is required between the SCORE and the Voice …"

>
> In the new-Staff case, the Score accepts the Staff.  Placing it in a StaffGroup is not considered.
>
> (Thanks for the rest of your reply too; I haven't digested it all yet.)
> —
> Dan
>