-
-
Notifications
You must be signed in to change notification settings - Fork 35
Clarifications to 'Resolved Values' section #1081
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't mind changing the accessor name, but see inline comments for a few things that need fixing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the name change could be clearer?
spec/formatting.md
Outdated
@@ -155,7 +156,7 @@ and different implementations MAY choose to perform different levels of resoluti | |||
> interface MessageValue { | |||
> formatToString(): string | |||
> formatToX(): X // where X is an implementation-defined type | |||
> getValue(): unknown | |||
> getResult(): unknown |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think getResult
is a bit odd, given that this is an informative illustration and it is about getting the resolved value. I'm not sure what a "result" is (one might construe it to be the result of formatting, which it emphatically isn't). I would suggest either getResolvedValue
(very literal) or perhaps resolveValue
(since presumably the resolved value is the result of some sort of resolving...)
(Note that resolvedOptions()
just below should probably be resolveOptions()
instead, if we do down this path)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea is that getResult()
returns the return value of the function handler; the resolved value is that return value, wrapped in an object that provides methods.
getResolvedValue()
doesn't seem right to me, since the resolved value is the thing implementing the MessageValue
interface, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since I think of MessageValue
as "wrapping" something, I thought of another name, unwrap()
, that returns the thing being wrapped. Let me know how that looks.
spec/formatting.md
Outdated
> - Using a _variable_, the _resolved value_ of an _expression_ | ||
> could be used as an _operand_ or _option value_ if | ||
> calling the `getValue()` method of its _resolved value_ did not emit an error. | ||
> calling the `getResult()` method of its _resolved value_ did not emit an error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is strangely worded compared to the bullets just preceeding. I would suggest instead
> - Using a _variable_, the _resolved value_ of an _expression_ | |
> could be used as an _operand_ or _option value_ if | |
> calling the `getValue()` method of its _resolved value_ did not emit an error. | |
> calling the `getResult()` method of its _resolved value_ did not emit an error. | |
> - A _variable in a _declaration_ could be used as an _operand_ or _option value_ | |
> if the result of `getResult()` does not emit an error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did a slightly different rewording; let me know what you think.
Co-authored-by: Eemeli Aro <eemeli@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that this continues to be a non-normative example, I'm fine with unwrap()
if the general sense is that it's more informative than getValue()
.
spec/formatting.md
Outdated
> 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. | ||
> - The relationship between the _operand_ and the result of the `unwrap()` method | ||
> is specific to each function. For example, with the built-in function `:number`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"built-in" isn't right? We call this the default function set or a default function, I think?
Also, use semantic line breaks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 3c301cb
spec/formatting.md
Outdated
> - The relationship between the _operand_ and the result of the `unwrap()` method | ||
> is specific to each function. For example, with the built-in function `:number`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like the is dancing around what we're trying to say. Perhaps:
> - The relationship between the _operand_ and the result of the `unwrap()` method | |
> is specific to each function. For example, with the built-in function `:number`, | |
> - The `unwrap()` method does not merely return the _resolved value_ | |
> of the _operand_. | |
> Instead, it returns the function-specific result of the function's operation. | |
> For example, the default function `:number` produces the implementation-defined | |
> numeric value of the operand, | |
> even if the original _operand_'s value were a literal. | |
> A different function might produce a transformed value instead. | |
> For example, an `:uppercase` function might produce an uppercase string in place | |
> of the original _operand_ value, | |
> or a function that extracts a field from a data structure | |
> might return the extracted value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See what you think about d70142f? In particular, I want to make it clear that the function handler returns a MessageValue
that has an unwrap()
method that returns something. This makes the text a little repetitive, but I'm open to suggestions.
Also, I know @mihnita didn't like the name unwrap()
, but in the WG meeting yesterday I wasn't hearing an alternative name suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... I want to make it clear that the function handler returns a MessageValue that has an unwrap() method that returns something...
The unwrap()
method/function returns something unless it emits an error, unless you presume that the ctor blows up on a bad value? A late-binding implementation might not bind the resolved value until required to do so, which might be very late indeed.
The more I think of it, the more I want to bikeshed the name towards MessageValue.resolvedValue()
, not because that's how you'd want to name an interface or its method but because we are consistent in calling the thing we're talking about a resolved value and the point of the example is to illustrate that concept. We don't talk about "unwrapping" anywhere. I'd go further and suggest that MessageValue
is wrong because its actually an Expression
interface (perhaps MessageFormatExpression
for clarity).
I think we do a good job not of illustrating that the method is not just required to resolve the operand, but that it might also apply local processing to it, which could include a change in type (for typed languages/environments).
I feel like the example should maybe be made less concrete, not merely start with "you're not required to do it like this" but to be more pseudocode-like, e.g.:
For example, an implementation might require function handlers
to provide an interface similar to:MessageExpression { getResolvedValue(), // unwrap if you prefer ... // to show we might be omitting stuff /* for functions that support selection note that I changed to match our new text */ Match(rv, key), BetterThan(rv, key1, key2), /* for functions that support formatting */ formatToString(), formatToX(), // where X is an impl-def type, perhaps to support a formatToParts functionality ... // other methods needed such as `isLiteral`, `isolate`, or `directionality` }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling the method "getResolvedValue" would be rather problematic, because the MessageValue (or MessageExpression in your example) itself is the resolved value. Note for example the language in :number
that refer to a resolved value being able to include option values.
Unless you're suggesting that we introduce a separate abstraction layer, and expect getResolvedValue()
to return an object which is wrapping a value and a bag of options? That seems unnecessarily complex for what's intended to be just an example.
It would also be misleading to call it "MessageExpression", as the same interface is also used in Literal Resolution and Variable Resolution, to determine the values of operands, options, and variant keys.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy with this discussion because it's the entire reason why I opened this PR :) We have a name for "resolved value", but we don't have a name for the thing inside the resolved value that is returned by unwrap()
/getValue()
/whatever. Because we don't have a name for it, it's easy to slip and call it the "resolved value", but the resolved value is the thing with methods on it. (At least in our example scenario.)
Instead of unwrap()
, what about getInnerValue()
or getOutput()
? Instead of MessageValue
or MessageExpression
, what about getWrappedValue()
? The best way I can think of what to describe what a resolved value is is that it wraps an implementation-specific value in an object with certain methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like the example should maybe be made less concrete, not merely start with "you're not required to do it like this" but to be more pseudocode-like, e.g.:
I like giving a complete TypeScript definition of the interface because if an implementor doesn't have strong opinions about how to represent things, they can just take that and adapt it to their implementation language. Or, what about beginning with the "pseudocode" version and ending with the complete interface?
I was re-reading the
MessageValue
example and noticed that it's easy to skip over what the last three methods are for, so I added a reference to the earlier text.I also thought that the
getValue()
method could have another name, since it's confusing to think about the "value" that it returns, vs. the enclosingMessageValue
. The name I thought of wasgetResult()
, but I'm open to other suggestions. I also thought it needed a little more explanation.