-
-
Notifications
You must be signed in to change notification settings - Fork 34
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
Add design doc on function composition #753
Add design doc on function composition #753
Conversation
Because the implementations for formatters and selectors | ||
naturally have different type signatures | ||
(a formatter consumes and produces a resolved value, | ||
while a selector produces a list of 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 think this is a flaw in the current specification. I think it would be much more general for a selector to match keys, rather than produce them.
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.
As currently specified, keys are indeed "matched", but the result of that match is a preferential list of keys.
It is also possible to simplify this API in an implementation so that the resolved value of the selector is expected to have a selectKey(keys)
method that returns a single key from its input list, rather than a preferential ordering, though the selection algorithm then gets a bit more complicated as it needs to track additional state (as done here). This works because the method can be called multiple times, each time leaving out the previously-best key from the input, to determine the full preference order.
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 like this design document; it sets out the options and their consequences pretty clearly.
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.
Added some inline comments.
Not having participated in the preceding ICU-TC mailing list discussion, I find the text in the document a little hard to follow. To me, it seems to be muddling together somewhat two spec layers:
- What's possible in general with functions and resolved values.
- What's the right thing for
:number
to do.
Untangling those would make it easier to follow what's being considered, as we need answers to both, and the specific answer for :number
is unlikely to be right for all other functions.
* Are named values essentially strings with metadata, | ||
or are they structured? (Model 1 vs. Model 2) |
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 not sure that I understand what the difference between these is, or what the ambiguity here is. Doesn't a "string with metadata" need to have an object wrapper of some sort providing slots for where to put the metadata? How is that different from being "structured"?
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.
You're right, this is vague. I tried to address this in 09aeff1, which runs the hazard of getting too implementation-specific, but I'm not sure how else to express it.
However, it _should_ make the requirements | ||
for "resolved values" | ||
clear enough so that implementors can | ||
make a well-informed decision | ||
on what these types and operations should be. |
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.
Is this the expected primary outcome of this work? As in, normative text or examples of (custom) functions operating on values with some expected results?
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 answer is that I'm not sure, and part of the goal of writing a doc that doesn't present a proposed solution is to narrow down what the outcome should be: normative changes and/or a set of use cases that must be supported (which would also be normative, but would be different from the style of the existing spec.) I was hoping that would happen as part of the discussion of this design doc.
I added some text along those lines in cfa882a. I also added some text at the end about different directions that a proposed design could go in. If there are any broad categories of solution that I left out, I'd like to include them.
I think that to answer your question, we have to pick one of those general directions.
A second constraint is | ||
the difficulty of developing a precise definition of "resolved value" | ||
that can be made specific in the interface for custom functions, | ||
which is implementation-language-neutral. |
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.
In general, I would be very happy for us to include a more concrete definition or description of "resolved values". Historically, that was one of the first parts of the formatting spec that I tried to include, in #198. Unfortunately, that PR ended up being stuck for a year, before needing to be dismissed. The preceding lengthy discussion in #190 is also relevant background, though note of course that these discussions are from over two years ago, so will not fully reflect our current thinking or nomenclature.
Given this past history, I would find it useful to hear @mihnita's current thoughts on defining "resolved value" more explicitly, as he in particular was previously against the idea.
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 would also be interested to hear from @mihnita -- in terms of the implementations, I took inspiration from his code in defining a FormattedPlaceholder
type that represents the return value of a function implementation, and trying to figure out how that type should actually work (in combination with #515) is how I got here.
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.
(and I'll take a look at those threads.)
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 tried to extract some of the top-level points from the lengthy discussion and added a "prior work" section: fa625c3.
If you think I've misrepresented anything or left out an important point, please let me know! I'm hoping that some of the questions that were challenging in those prior discussions might be easier to resolve now due to spec changes that have happened in the meantime. But not having been there for those discussions, I can't be certain of it.
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.
Re-reviewing this PR and the changes since my last review, I believe further progress on this is still blocked by waiting on input from @mihnita, as requested above. I would find it important to get buy-in on the general approach before spending more time on this.
I suspect that just this one paragraph might not address your concern about untangling the two concerns, though. I'll try to keep that in mind while answering the other comments. |
…ng areas of ambiguity
…onomize possible solutions
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 design doc is good -- it covers the space of design decisions well around functions whose return values effectively get passed to other functions.
I left a few comments and small optional suggested edits, but shouldn't be considered a blocker.
These issues are important to decide upon so that we can avoid ambiguity and complexity.
The objective of this design document is not to make | ||
a concrete proposal, but rather to explore a problem space. | ||
This space is complicated enough that agreement on vocabulary | ||
is desired before defining a solution. | ||
|
||
Instead of objectives, we present a primary problem | ||
and a set of subsidiary problems. |
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 this is a good description of this document.
I think that we still will want a concrete design document, but this is a necessary preamble to that effort.
|
||
So we must address both problems together: | ||
|
||
* Problem 1: Define what it means for functions to compose with each other. |
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 know that this is actually a problem. I think it is a side-effect of not resolving Problem 2.
I suspect the behavior is that some (but not all) functions and some (but not all) options can affect the operand.
Example:
.input {$d :datetime dateStyle=medium timeZone=|America/Los_Angeles|}
.local $t = {$d :datetime timeStyle=short}
{{What prints? {$d} {$t}}}
In the above, I don't want to have to type the timeZone
option every time I touch the value. I probably want that to be transitive. I don't want $t
to print both the date and time, though: I asked for the time when assigning the local value. $d
is probably some Temporal value (or even a classical incremental time value). (It doesn't matter if you don't agree with whether I'm right about the date/time styles being transitive.)
Similarly, think about this message:
.local $i0 = {|Ϊ́| :casefold} // literal is U+03AA U+0301
.local $i1 = {$i0 :normalize form=nfkc}
.local $i2 = {$i1 :casefold}
.local $i3 = {$i2 :normalize form=nfkc}
{{Prints the intended U+0390: {$i3}? see https://www.w3.org/TR/charmod-norm/#normalizationAndCasefold}}
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 know that this is actually a problem. I think it is a side-effect of not resolving Problem 2.
I disagree with this, because I think that even if we resolved Problem 2, we would still have ambiguities.
In your first example: suppose we solve problem 2 by adopting a representation of function results that includes all the options that were passed in. Without further spec work, though, it's still unclear whether $t
is printed with the time zone or not. Problem 2 is "what do functions return?", while problem 1 is "what do functions do with their inputs?" Maybe the latter question can only be answered in a way that's specific to each function.
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 think example 1 is an exemplar of "what do functions do with their inputs" as I don't think that options are necessarily the same thing as "inputs". Also, it's probably not a great example, since Temporal types provide ways to float/unfloat time values (making the time zone a part of the datetime value--that it, modifying the operand, as it were) rather than merely being a random option.
My concern is that, whenever I see "we have to solve two problems at the same time", that suggests extra effort to ensure that there's been complete decomposition of the requirements.
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.
Re: decomposition of the requirements, fair enough... what do you think about the change to this section I made in 86c26ff (emphasizing that this document is mainly about solving the resolved value problem, which is only a part of the bigger function composition problem)?
Co-authored-by: Elango Cheran <[email protected]>
Co-authored-by: Elango Cheran <[email protected]>
The following seems contradictory:
That is, Alternative 1 (formatted value only) seem to match Model 2, not Model 1. This happens in a few other places as well. I think the readability would be improved dramatically if the Models had names instead of numbers, something like: Model 1 --> Bundle Model |
This design doc partially addresses #515. It covers some of the same ground as the design doc in #645, but should be seen as a prequel to #645.
Before getting into solutions, I thought it would be useful to collect together some examples and questions, omitting the last two sections from the design doc template.
This document is also an attempt to summarize the ICU-TC mailing list discussion that included @macchiati, @markusicu, @echeran and @richgillam . (Some of the comments, which fall more under "proposed solutions", will be included in a future sequel to this design doc.)
My goal is to get this document into a state that everyone can agree on before finishing part 2 (with the proposed solutions).
I invited some reviewers on an "in case you're interested" basis.