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
[RFC] Type system ordering of: object interfaces, directive arguments, input object fields, enum values #1063
base: maintain-order
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for graphql-spec-draft ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
spec/Section 3 -- Type System.md
Outdated
@@ -1473,7 +1474,7 @@ EnumValuesDefinition : { EnumValueDefinition+ } | |||
EnumValueDefinition : Description? EnumValue Directives[Const]? | |||
|
|||
GraphQL Enum types, like Scalar types, also represent leaf values in a GraphQL | |||
type system. However Enum types describe the set of possible values. | |||
type system. However Enum types describe the list of possible values. |
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 considered "However Enum types describe as a list the set of possible values." but it didn't seem worth the extra words.
The prior presence of “set” to me unambiguously implied unordered. Your switch to “list” i think is likely? a weaker implicit association with ordering for serialized content via introspection. This proposal definitely works (happy to support it), but i think we needed top level or inline definitions/assertions about what terms (eg list) apply ordered or not. |
I don't think the term "set" itself implies ordered or unordered, "set" is independent of ordering. For example in JavaScript a
I agree. The term "list" itself is not as unamiguously "ordered" as I at first thought; for example here's an excerpt from an A-level Computing syllabus in the UK:
Similarly HTML has both An alternative fix would be to leave the existing wording as-is (but maybe slightly edited for consistency) and instead indicate that all lists and sets in the spec are ordered unless otherwise stated. We currently leave the order to be "implementation defined". Essentially, we are asking the question "are the two following schemas the same?": enum E {
A
Z
}
type Query {
a: E
} enum E {
Z
A
}
type Query {
a: E
} I'd argue that they are not, and that the order of the enum is significant. A change in that order would trigger a change in the printed SDL that you might version control, a change in any generated documentation, a change in browsing it in GraphiQL, and could have many other consequences elsewhere (for example code generation). We should definitely be more explicit about this. |
I've added a note to the beginning of the spec 👍 |
spec/GraphQL.md
Outdated
**Lists Are Ordered** | ||
|
||
Unless otherwise stated (for example, "an unordered list"), any mention of the | ||
term "list" in this document indicates an ordered collection. |
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.
Almost feels like we need to differentiate between syntax order and semantic (~execution?) order. In the syntax, I think I always want determined order. At execution, sometimes the order is unimportant like for input object literals.
Don't want to bikeshed this more than needed though. This PR is a net improvement to clarity so I'm all for 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.
The coercion of input objects is explicitly unordered: https://spec.graphql.org/draft/#sec-Input-Objects.Input-Coercion; the order of a literal is arguably important though, e.g. {f(o:{a:1,b:2})}
and {f(o:{b:2,a:1})}
are concretely different documents even though the coerced interpretation of the o
argument is equivalent.
spec/GraphQL.md
Outdated
**Lists Are Ordered** | ||
|
||
Unless otherwise stated (for example, "an unordered list"), any mention of the | ||
term "list" in this document indicates an ordered collection. |
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.
👍 . Thanks--this catch-all I think does a lot of important work 😃
Following up on this after the discussion in the WG meeting today, my suggestions:
This was a bit of a riff, so edit away: ## A.6 Data Collections
This specification describes the semantic properties of data collections
using types like "list", "set" and "map". These describe observable data
collections such as the result of applying a grammar and the inputs and
outputs of algorithms. They also describe unobservable data collections
such as temporary data internal to an algorithm. Each data collection
type defines the operations available, and whether values unique or ordered.
**List**
The term "list" describes a sequence of values which may not be unique.
A list is ordered unless explicitly stated otherwise (as an "unordered
list"). For clarity the term "ordered list" may be used when an order
is semantically important.
**Set**
The term "set" describes a unique collection of values, where each value
is considered a "member" of that set. A set is unordered unless explicitly
stated otherwise (as an "ordered set"). For clarity the term "unordered set"
may be used when the lack of an order is semantically important.
**Map**
The term "map" describes a collection of "entry" key and value pairs, where
the set of keys across all entries is unique but the values across all
entries may repeat. A map is unordered unless explicitly stated otherwise
(as an "ordered map"). For clarity the term "unordered map" may be used
when the lack of an order is semantically important.
Note: To improve legibility, when possible implementations should preserve
observable order for unordered data collections. For example, if an applied
grammar to an input string results in an unordered set, serializing that
set (to a string or other observable output) should produce the same order
found in the original input string. |
@leebyron I've changed list, set and map into definitions and have also changed the final non-normative note into a normative statement since it uses the word I've also attempted to implement your other suggestions, and have then gone through and corrected the types throughout section 3, for example an object doesn't define a list of fields but more an ordered set of fields... ... except, is it really a map where the field names are the key? I'll add this to the WG next month. |
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 clarification is nice!
This has been split into 3 PRs, it's now the top PR on top of: |
UPDATE 2024-04-05: Following last night's WG meeting, this PR has been split into 3 parts, and is now stacked behind these PRs:
As raised by @cdaringe in #1062, enum values don't dictate an explicit order. On scanning through the spec in more detail, it turns out this is true of a few other things too.
Everything in SDL is implicitly ordered (since it's a textual representation, one thing after another) and everything in introspection is implicitly ordered (because it's represented via lists). E.g. in introspection,
enumValues
is a list, and a list is inherently ordered.I feel it's an unwritten rule that GraphQL introspection should be stable (i.e. introspect the exact same schema twice with the exact same introspection query and the results should be the same). Thus, there should be an order (dictated by the schema designer), and I'd like to make that more explicit.
I researched the current status, and I think we can start to fix this with the few minor edits I made to the spec in this PR, in particular:
set
(which is generally perceived as unordered) to the wordlist
(which is always ordered),Generally this was achieved by copying text from similar things, e.g. the directive arguments copied from field arguments; input object fields copied from object fields.
I know that @IvanGoncharov has been very careful in graphql-js to ensure that ordering is stable, I believe he ensures that introspection -> SDL -> introspection always results in the same results.
Status before this PR (emphasis mine)
Object fields: ordered ✅
Object field arguments: ordered ✅
Object interfaces: not declared? 😞
(I couldn't find anything in Section 3 declaring set/list.)
Input object fields: a "set" ❌
Enum values: a "set" ❌
Directive arguments: not declared? 😞
(I couldn't find anything in Section 3 declaring set/list.)