-
Notifications
You must be signed in to change notification settings - Fork 18k
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
proposal: spec: Default / Optional function parameters #21909
Comments
Related to #12854, which I believe is a better solution to this. Damien's first example shows how optional arguments could effectively be accomplished. |
I believe #12854 or https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis are superior solutions to this problem. I don't think default arguments could be made to fit into Go without a great deal of complexity. They raise a number of questions: Given a type with a method Is the default value part of the type? If not, then it's unclear why two functions of identical type can be called differently. If so, why is this just for func parameters—why can't I write What does this print:
While I'm sure these could all be worked out, they all have serious implications for the complexity of the language specification and implementations and hence a programmer's ability to reason about Go programs. |
The question you need to ask is will that function break when it tries to call M(A) on a value of type M(A,B=D)? Clearly it will not, so all is fine. |
This should be pretty much equivalent of:
Thus it will not be influenced by a new call. If the default argument is initialized with a global variable, the regular rules apply (i.e. whether it's a pointer or not). In both cases it seems the generated code would be the same, I think. I do not see a purpose for optional parameters, if default ones are supported. They seem like a special case that we can go without. |
This feature was deliberately omitted. See the discussion in talks/golang.org/2012/splash.article about default arguments. They are a bad idea as they make it much easier to build confusing functions that complicate the API. |
API patching is a concern, but the thing is, nothing prevents us from doing such patching even now. Right now we can and do use either structs or functional arguments do achieve default/optional arguments (the stdlib even uses struct pointers for this), and there's nothing stopping anyone from adding an extra function or struct key later on, which doesn't match the current behaviour of the API. So the current situation is that it is a bit more cumbersome, without actually solving the problem cited in the article. Furthermore, the current solutions have a much higher initial cost of creation, especially for functional arguments; and that's for a feature that seems to have proven its usefulness. A decend support for default arguments will only result in a cleaner and more understandable code in the long run. |
@urandom There are always ways to circumvent the current situation but as @robpike said, there's good reason for the status quo. Also "usefulness" of a feature is not a meaningful argument for its inclusion. Virtually every feature is "useful" in some way or another, otherwise it wouldn't be proposed. |
@urandom: "support for default arguments will only result in a cleaner and more understandable code in the long run". That's just it, the designers of the language disagree with that claim when applied to large code bases. As code with default arguments grows, it too often becomes harder to understand, not easier, as functions and their invocations become more intricate and more entangled. I consider this issue closable but will let discussion continue. |
It is more than just about optional arguments. It also raises the prospect of named arguments, which have their own value. What is easier to understand? F(3.44, 2.44, 5.44, 7.55, 3.141, 6.666) OR F(width=3.44, height=2.44, depth=5.44, color=7.55, velocity=3.141, weight=6.666) On top of named arguments, you then also have the prospect of kwargs style argument passing/receiving, yes we are basically talking about Python here. The point is there are more advantages to optional parameters than merely them having default values. |
@fcntl The designers of the language have also contemplated named arguments. One thing to consider is what programming style should be enforced once a language provides named arguments (and people invariably will want to enforce a style): Must they always be named? Never? Only when there's more then 3 arguments? Can some names be left out? Does the order matter? Should it be always in declaration order for readability? Why not? etc. etc. It opens a Pandorra's box of questions that need to be answered. The marginal (in most cases) benefit comes at a cost that is not commensurable. More generally: If you have a lot of code like with 5 or more arguments, and it's not regular (say as part of building a large table), you probably should rethink your approach. In those cases it's probably better to pass a struct and then you can name the fields as you please. Finally, there are comments. In other words, Go provides you with plenty of mechanisms to write readable function calls even without the ability to explicitly name your arguments. |
Complete agree. Furthermore, that with ~2.5 years of experience with a medium-sized Typescript project (which I'll grant you is not a huge evidence base), writing the language, writing tools to work with the language (this is a hugely important consideration from our perspective)... Go's current position is far preferable, for at least all the reasons outlined by @robpike, @griesemer and others. |
I feel like we sort of need some solution here, right now there's maybe 6 or 7 reasonable ways to define "options" with defaults, using the functional style, structs, methods, chained methods, zero values, tags, etc. None of them are very self-documenting, you can't see what the default values are really, or they're arbitrarily embedded in tags. To me at least one of my favorite things about Go is that it's opinionated and most Go code looks very similar, however, I feel like this is a big part of where they all start to differentiate and it's such a common task, people shouldn't be burning cycles on it ideally. |
Closing this approach in favor of #12854, as discussed above. |
Languages like Python and TypeScript supply ways to omit arguments when calling with either a default provided, or just none at all.
Default parameter example from Typescript:
Optional parameter example from Typescript:
Use Case
For instance, creating a reader:
This can be compressed into one function:
The text was updated successfully, but these errors were encountered: