-
-
Notifications
You must be signed in to change notification settings - Fork 35
Description
Originally posted by @macchiati in #1094 (comment):
I agree that the terminology is very confusing. For example, a resolved value is not a "container" as the following implies (my bolding).
The resolved value of an expression with a
:string
function
contains the string value of the operand of the annotated expression,
together with its resolved locale and directionality.
None of the options set on the expression are part of the resolved value.
It is instead suggested that an RV is like the class definition given in https://github.com/unicode-org/message-format-wg/blob/1f87da0574e793972d84532b25dc950115734739/spec/formatting.md#resolved-values
While this specification does not require it, a resolved value could be implemented by requiring each function handler to return a value matching the following interface:
interface MessageValue {
formatToString(): string
formatToX(): X // where X is an implementation-defined type
unwrap(): unknown
resolvedOptions(): { [key: string]: MessageValue }
match(key: string): boolean
betterThan(key1: string, key2: string): boolean
directionality(): 'LTR' | 'RTL' | 'unknown'
isolate(): boolean
isLiteralOptionValue(): boolean
}
But that really doesn't sit very well at all with saying "contains the string value". Instead, we'd really have to say exactly what each of the methods do. And we don't do that.
If we are going down this road, we could be more specific, and replace "While this specification does not require it, a resolved value could be implemented by requiring each function handler to return a value matching the following interface:"
by the following (we use the "logically equivalent" language at many places in Unicode):
A resolved value is logically equivalent to a value matching the following interface:
We can then just have a standard table for each method, with the 2nd column's cell describing what it does; that way we won't miss something important (like describing whether the unwrap() method produces a value (vs an error) and if so, what the value is defined to be.)
No implementation is required to use those names or functions internally, but that is a more concrete, uniform way to describe what a function does and does not do
BTW
- I think 'unknown' above would be much better as 'Y // where Y is an implementation-defined type'.
- The above also implies that resolvedOptions has exactly 1 key-value pair, whereas I think the intent is that it return a map with 0 or more key-value pairs.
- I find the unwrap() name and explanation to be particularly obscure.
- The grammar of the following sentence is a bit fuzzy:
- The resolved value of an expression could be used as an operand or option value if calling the unwrap() method of its resolved value did not emit an error. (This requires an intermediate variable declaration.) In this use case, the resolvedOptions() method could also provide a set of option values that could be taken into account by the called function.
- I think it is intended to be something like:
- The resolved value of an expression can be used as an operand or option value, but only if calling the unwrap() method does not emit an error. In that case, then resolvedOptions() method provides a set of option values that can be taken into account by the called function. These option values may be a subset of those used to create the resolved value.