#Optional vs default
1 messages Β· Page 1 of 1 (latest)
Oh sorry
I meant to link to this https://github.com/dagger/dagger/issues/6749
So to go back to my problem with apko:
- In your Bass module, you define an argument with a default value. No explicit mention of "optional".
https://github.com/vito/daggerverse/blob/main/apko/apko.bass#L55
(defn alpine [
:branch branch "edge"] => :Container
- Bass SDK exposes this as a GraphQL argument that is non-nullable, and has a default value:
alpine(branch: String!="edge"): Container!
- The Go SDK introspects this graphql schema, and that determines the argument is not optional, because it's not nullable. As a result it generates the following Go binding:
func Alpine(branch string)
Instead of what you expected/wanted:
type AlpineOpts struct {
Branch string
}
func Alpine(opts ...AlpineOpts) {}
So one fix would be to clarify our own "common SDK spec", to say two things:
-
Use of term "optional". If SDKs use the term "optional" in their DX, it should mean "the opposite of required: either has a default value, or is nullable". Corollary: "if an argument has a default value, it is optional. Design your DX accordingly".
-
When generating bindings, consider arguments that are either nullable, or have a default value, as optional.
(cc @hexed beacon for continuity from 6749)
I can make this a comment in that issue
Applying these rules would mean two things specifically for the Go SDK:
+default=...would imply+optional(and that would have be documented somewhere)- Codegen would be changed so that non-null arguments with a default values are recognized as optional
For the first point, I think you wouldn't want // +optional to additionally imply nullable right?
Like, if // +default implies // +optional but // +optional now means nullable, that would prevent you from having a non-null with a default
How would you define +optional today?
It can't just be "optional", because there are several ways an argument can be optional in the standard definition
Today it's basically // +nullable, for better or worse. Sorry, previous msg implied it doesn't - it's not "now means", it always meant that. Double checking
Ah got it
(confirmed)
I think we would have to keep it
Maybe we rename it to avoid confusion?
Maybe we don't have to say precisely in the Go SDK docs: +optional means nullable
though, string // +nullable is a bit confusing - since the value itself isn't nullable, it'd be nullable in GraphQL but in Go you'd get ""
yeah I would avoid using that term altogether, the truth is, it doesn't map well to the Go DX anyway
So I would just abstract it away.
So basically, +default and +optional are 2 ways to define an optional argument
+optional basically means "Make this argument optional. Implied by +default. If no default value is defined, the SDK will choose a default value based on the type."
+default means: "Define a default value for an optional argument. Implies +optional."
Who knows, in the future there may be a separate introspection API where you can ask your runtime whether a given argument was set or not
Given the above, in theory we could make the Go DX slightly less confusing for example by renaming +default to +optionalWithDefault but may not be worth it
Made some edits and landed on this:
+optional: make this argument optional. If no default value is defined (see +default), the SDK will choose a default value based on the type.
+default: define a default value for an optional argument. Implies +optional.
Second part of +optional confuses me a bit - does that imply it's installing a default like "" into the schema, or only that the SDK will provide a sane default value to the function call (i.e. Go zero-value, None in Python, whatever)? Is it worth mentioning that it translates to a nullable type at the schema layer? (Guessing no since we're trying to abstract that, just trying to clarify)
Yeah I guess it's left unspecified whether the "default default" value will be visible in the schema, or just a nullable field
I don't think it matters to the native dev though
Since it doesn't matter to their clients on the other end either
Also worth noting these // +optional and // +default pragmas are Go only; Python uses native default values, TS too I presume
It might just never come up in other SDKs
6749 seems to cover all that
but yea, I guess the same scenario would come up for any other language that doesn't have native defaults, it could make sense to codify those pragmas anyway (in spirit, not in syntax, since every language also has a different opinion on comment pragmas)
π
while we're making changes π
@outer brook mentioned above:
yeah, nullable vs optional conflation has come up before. it also kind of ties in to type inference; you could imagine in Go something is implicitly optional if it's a pointer. but we can't do that because all objects are pointers regardless
I think we do do that for pointers to primitive types like string but not sure
I ran into this the other day... can we get rid of this behavior? I think it's kind of confusing, I would've proposed doing this before when adding pragmas, except somehow I was unaware of it's existance π
By that you mean requiring // +optional instead of making it a pointer? I'd be onboard, pointers are pretty clunky to deal with anyway