Skip to content
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

Editorial: Examine+reduce the diversity of forms in PR #2877 #2972

Merged
merged 13 commits into from
Jan 25, 2023

Conversation

jmdyck
Copy link
Collaborator

@jmdyck jmdyck commented Dec 14, 2022

At the latest editors call, I was invited to expand on #2877 (comment), giving specific cases instead of just counts. That's what this PR does.

Most of the commit messages have a relevant excerpt from that comment and some discussion.

spec.html Outdated Show resolved Hide resolved
@michaelficarra
Copy link
Member

For ab4c875 and 7550efd, I strongly prefer keeping the "either".

Similarly, for c579c42 I prefer keeping "any of" or "one of", and for a508279 I prefer keeping "one of".

@michaelficarra michaelficarra added the editor call to be discussed in the next editor call label Dec 15, 2022
@jmdyck
Copy link
Collaborator Author

jmdyck commented Jan 5, 2023

Okay, now that I have a better idea of editors' preferences, I've dropped the "descriptions" commits. Instead, since this PR is labelled "establishes editorial conventions", I've attempted to formulate a convention and then supply commits to bring things into line.


We often need to express that the value of an alias (or other meta-expression) belongs to some target set of values. E.g.,

  • In an algorithm, to check whether the value of _X_ is a String value, we say if _X_ is a String.
  • In a structured header, to assert that parameter _X_ is a String value, we say _X_: a String.

In both of the above examples, the target set of values is expressed the same way ("a String"). But things get interesting when the target set cannot be expressed that simply. For example,

  • in an algorithm, we might say if _X_ is either a String or *undefined*, whereas
  • in a structured header, we would say _X_: a String or *undefined*.

(I.e., one uses "either" and the other doesn't.)

So here, we consider when the target set is a union of smaller sets, expressed as a disjunction of descriptive terms, which I'll generalize as {D}.

For example, a {D} might be:

  • a String
  • *undefined*
  • ~empty~
  • an Object that has a [[Foo]] internal slot
  • a List of <things>
  • a normal completion containing <something>

The wording we use for the disjunction depends on its context, specifically what precedes it.

(1) When it's preceded by prose (typically the word "is")...

The conventional forms are:

  • {D}
  • either {D} or {D}
  • one of {D}, {D}, ..., or {D}

E.g.:

  • _X_ is *NaN*
  • _Y_ is either a Number or a BigInt
  • _Z_ is one of an Object, *null*, or *undefined*

[The 4 new commits bring the spec in line with this convention.]

(2) Otherwise, the disjunction is preceded by:

  • a colon (when a structured header declares the 'type' of a parameter or return value)
  • the start of a table cell (when a table that 'declares' the fields of a record or the internal slots of an object
    gives the 'type' of the field or slot, typically in the column labelled "Value Type"), or
  • a left paren (in an 'inline' declaration of a Record schema).

Here, the conventional forms don't use "either" or "one of":

  • {D}
  • {D} or {D}
  • {D}, {D}, ..., or {D}

E.g.:

  • _X_ : a String
  • _Y_ : a Number or a BigInt
  • _Z_ : an Object, *null*, or *undefined*

But if {D} or {D} would be ambiguous, then use one of these forms:

  • either {D} or {D}
  • either {D}, or {D}

For example, a List of Strings or *undefined* is ambiguous. It could mean:

  • a List of (Strings or *undefined) or
  • (a List of Strings) or *undefined*

By using 'either', we can say (respectively):

  • a List of either Strings or *undefined* or
  • either a List of Strings or *undefined*

(Similarly, a normal completion containing {D} or {D} is ambiguous and so needs 'either'.)

The version with the comma is helpful when the first {D} is itself complicated, e.g.:

  • either a normal completion containing either a Number or a BigInt, or a throw completion

[No commits needed.]

@jmdyck
Copy link
Collaborator Author

jmdyck commented Jan 5, 2023

(Looks like ecmarkup doesn't like either a normal completion containing one of A, B, or C, or a throw completion.)

@michaelficarra
Copy link
Member

@jmdyck That summary LGTM.

@syg
Copy link
Contributor

syg commented Jan 11, 2023

I think the "one of an X" form sounds strange. From the editor call discussion, the following would sound more natural.

A disjunct is either a type with >1 inhabitant (styled as X below) or a constant (styled as "foo" below).

  • If there are exactly 2 disjuncts and both disjuncts are types, or both disjuncrs are constants, say "either {D} or {D}"
  • If there are exactly 2 disjuncts and one disjunct is a type and the other is a constant, put the type before the constant, and say "either X or "foo""
  • If there are >=3 disjuncts and all disjuncts are types with >1 inhabitants, say "either an X, a Y, or a Z"
  • If there are >=3 disjuncts and all disjuncts are constants, say "one of "foo", "bar", or "baz""
  • If there are >=3 disjuncts and some are types and some are constants, put all the types before the constants, and say "either an X, a Y, a Z, or one of "foo", "bar", or "baz""

@michaelficarra michaelficarra removed the editor call to be discussed in the next editor call label Jan 11, 2023
@jmdyck jmdyck force-pushed the 2877_ed branch 2 times, most recently from 0ffbd65 to 4f2688e Compare January 15, 2023 15:58
@jmdyck
Copy link
Collaborator Author

jmdyck commented Jan 15, 2023

Okay, I made some more changes and then re-divided things with respect to @syg's bullets.

  • If there are exactly 2 disjuncts and both disjuncts are types, or both disjuncts are constants, say "either {D} or {D}"

2 commits, inserting "either" to a few cases that didn't have a prefix (5 cases with two types, 3 cases with two constants).

  • If there are exactly 2 disjuncts and one disjunct is a type and the other is a constant, put the type before the constant, and say "either X or "foo""

1 commit, swapping the order in 1 case.

  • If there are >=3 disjuncts and all disjuncts are types with >1 inhabitants, say "either an X, a Y, or a Z"

2 commits, inserting "either".

The second commit is where the disjunction is after "is not", in case you want to consider negatives differently.

  • If there are >=3 disjuncts and all disjuncts are constants, say "one of "foo", "bar", or "baz""

3 commits,

  • changing "either" to "one of" (1 case),
  • changing "any of" to "one of" (22 cases), and
  • inserting "one of" (1 case).
  • If there are >=3 disjuncts and some are types and some are constants, put all the types before the constants, and say "either an X, a Y, a Z, or one of "foo", "bar", or "baz""

Currently, the spec has only 5 occurrences of this, and they're all 'degenerate', in that either the number of types or the number of constants is 1.

  • For 3+ types + 1 constant, I assumed either an X, a Y, a Z, or "foo" (1 commit to put the constant last in 1 case).
  • For 1 type + 2 constants, I assumed either an X or one of "foo" or "bar" (1 commit to insert "or one of" in 3 cases).

Personally, I think the changes of that last commit aren't an improvement. Note that all 3 cases are embedded within a "normal completion" type, so e.g., the status quo's
either a normal completion containing either an Object, *null*, or *undefined*, or a throw completion
is changed to:
either a normal completion containing either an Object or one of *null* or *undefined*, or a throw completion

@bakkot
Copy link
Contributor

bakkot commented Jan 18, 2023

From discussion this all looks good except in the case of mixing types and constants, where we'd prefer to mix them in a single list (still with the constants at the end) and use either rather than one of regardless of how many items there are. (Contrary to the last call, now that we've seen it written out- thanks!)

(Also I'll need to update ecmarkup to understand "one of".)

@jmdyck
Copy link
Collaborator Author

jmdyck commented Jan 19, 2023

From discussion this all looks good except in the case of mixing types and constants, where we'd prefer to mix them in a single list (still with the constants at the end) and use either rather than one of regardless of how many items there are.

Okay, I've dropped my last commit, so those 3 cases have reverted to the format you describe.

Copy link
Contributor

@bakkot bakkot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for doing this.

Copy link
Contributor

@syg syg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, thanks for bearing with all the requests

> Composing a condition from sub-conditions...
>
> ... when there are only 2 sub-conditions:
>
>   229  {COND} and {COND}
>    80  {COND} or {COND}
>     4  {COND} unless {COND}
> vs
>     2  {COND}, or if {COND}
>     1  {COND}, or {COND}
>     1  {COND}, unless {COND}
> vs
>     1  either {COND} or {COND}

This commit reduces the variety slightly:

- `{COND}, or {COND}`: Change `or` to `or if`
- `either {COND} or {COND}`: Delete `either`
> Composing a condition from sub-conditions...
>
> ... when there are 3+ sub-conditions:
>
>     1  {COND}, {COND}, or {COND}
>     8  {COND}, {COND}, and {COND}
>     6  {COND}, {COND}, {COND}, and {COND}
> vs
>     5  {COND} and {COND} and {COND}
>     1  {COND} or {COND} or {COND}
>     1  {COND} or {COND} or {COND} or {COND}

This commit converts the latter style into the former.

----

I considered the opposite direction, but found that it resulted in at least one ambiguity, e.g.
`If there exists <something> such that {COND} and {COND} and {COND}`
could be
`If (there exists <something> such that {COND}) and {COND} and {COND}`
or
`If (there exists <something> such that {COND} and {COND}) and {COND}`
or
`If (there exists <something> such that {COND} and {COND} and {COND})`

Note that, regardless of the style chosen for 3+ sub-conditions, a similar ambiguity would already exist for 2 sub-conditions, e.g.:
`If there exists <something> such that {COND} and {COND}`
However, it turns out that the spec has no conditions of that form. (At least, not in algorithms.)
> (And while I'm here, conditions that mix operators without parens:
>
>     1  {COND} and {COND} or {COND} and {COND}
>     3  {COND} and {COND}, or if {COND} and {COND}
>     2  {COND} and {COND}, or {COND} and {COND}
>     2  {COND} or {COND} <ins>and {COND}</ins>
>     1  {COND} unless {COND} and {COND}
>     2  {COND}, or if {COND} and {COND}
>
> )

This commit changes
- 1  `{COND} and {COND} or {COND} and {COND}`
to the ", or if" form.

The "unless" (in WordCharacters) is probably okay.
It's in an Assert, so isn't normative anyway.

The 2 `{COND} or {COND} <ins>and {COND}</ins>`
(in Annex B's early error rules for ClassRanges) are weird.
I think there's a bigger refactor that will eliminate them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants