Open lucacasonato opened 1 month ago
This representation is not permitted because it breaks immutability. Variable values are immutable in MF2. A value can be annotated using a declaration, but the value itself cannot be changed.
A .input
provides a way to annotate (but not change) a value passed in. So .input {$count :integer}
says that there must be a variable count
passed in (or you'd get a resolution error) and adds an annotation asking for it to be formatted/selected as an integer.
A .local
provides a way to assign a new value. So .local $count = {:expression}
provides a way of assigning a value to the name count
. If you want to change the value of an existing value count
, you have to assign it to another name, e.g. .local $count1 = {$count :something}
.
This is described by the design on variable mutability
Ok, then my understanding of what .input
is is wrong - I described my initial understanding in https://github.com/unicode-org/message-format-wg/issues/818.
This example being allowed makes no sense to me then: https://messageformat.dev/playground/#LmlucHV0IHskY291bnQgOm51bWJlciBzdHlsZT1wZXJjZW50fQp7e3skbmFtZX19fQ.ewogICJuYW1lIjogMTIzCn0.ZW4tVVM
This example being allowed makes no sense to me then: https://messageformat.dev/playground/#LmlucHV0IHskY291bnQgOm51bWJlciBzdHlsZT1wZXJjZW50fQp7e3skbmFtZX19fQ.ewogICJuYW1lIjogMTIzCn0.ZW4tVVM
The example message is:
.input {$count :number style=percent}
{{{$name}}}
The inputs supplied include name
but not count
. Since the pattern does not reference $count
, the message can format without triggering an error ($count
is never used).
An implementation is permitted to do eager evaluation, in which case this message could cause an Unresolved Variable error. However, we have some group members who are strongly committed to lazy evaluation. Such an implementation would never detect the unresolved variable (unless we require every declaration to be evaluated, which breaks lazy evaluation).
Note that lazy or semi-lazy evaluation allows for messages to reference variables that are only sometimes passed in and to annotate those values. For example:
.input {$delivery :datetime dateStyle=long timeStyle=long}
.match {$packagesDelivered :integer}
0 {{No packages were delivered}}
one {{{$packagesDelivered} package was delivered: {$delivery}}}
* {{{$packagesDelivered} packages were delivered: {$delivery}}}
$delivery
only matters if packagesDelivered
!= 0.
Admittedly this sort of message is rare and somewhat unusual.
Whoops - its late here. The right message and data would be: https://messageformat.dev/playground/#LmlucHV0IHskY291bnQgOm51bWJlciBzdHlsZT1wZXJjZW50fQp7e3skY291bnR9fX0.ewogICJjb3VudCI6IDEyMwp9.ZW4tVVM
.input {$count :number style=percent}
{{{$count}}}
This behaves like I had initially thought. I then do not understand why this is not identical to a theoretical:
.local $count = {$count :number style=percent}
{{{$count}}}``
At least in the data model, these are semantically equivalent.
Those would be semantically equivalent. We don't allow that because we have a consensus around variable immutability. See the design doc quoted elsewhere. But the data model with the change proposed in #799 would no longer care about that (there would be no data model difference). I assume you agree with the change in #799?
Yeah - that change in #799 seems very good.
Consider the following message:
From my understanding this would be identical to the following message, were it allowed.
I understand this is not allowed, due to the following syntax restriction:
This does make me wonder why we distinguish between these at all in the data model. They are objectively identical outside of syntax. It is only in the MF2 syntax that these are different.
In a potential combined data model for these two it would also trivial to tell whether a given declaration came from an input or a local declaration, due to the syntax restriction from earlier - if a declaration has the same variable on the left and the right, then it came from a
.input
, otherwise it came from a.local
.