[Pitch] Optional parameters in functions should default to `nil`, allow omission

Congratulations on your first proposal!

I'm -1 on this idea, because I suspect it will add extra pitfalls for projects when evolving their APIs. You've called this out already in the "source breaking change" note, and I think that's reason enough to not go down this road.

One reason this can happen in real projects is as part of library API evolution. As an API grows, you will likely grow new methods that enable extra flexibility. This flexibility will manifest, at least some of the time, in being able to pass new arguments to existing functions. Right now it is always possible to avoid the ambiguity while adding Optional parameters by refusing to give them a default value. With this change, evolved parameters may never have an Optional type, even when that type is semantically meaningful, as they will encounter this ambiguity.

I'm disinclined to introduce ambiguity of this form, so I'm -1 on the proposal. If it were accepted, I'd want to argue for warning at the call site, not at the compile site, as the call site should take action to disambiguate which call they want.

3 Likes

These are good examples.

My point, not clearly made, was any language where it’s not an error to omit a an optional parameter (or not initialize an optional variable) will assign it to nil (or sometimes 0, which was the poor man’s placeholder for nil not long ago) if it’s not manually given a value.

And you can, in fact, put optionals with defaults at the beginning of the properties right now. It would be processed by the compiler the same way if those optionals didn’t have explicit defaults but were instead assigned nil.

1 Like

Ah, understood.

My earlier comment was from my phone earlier, so I didn't have an opportunity to test it, but it looks like the following is a completely valid Swift signature (much to my chagrin), and Xcode presents autocompletion options both with and without bar:

func myFunc(foo: Int, bar: Int = 3, baz: Int)

Since that behavior is already supported, I don't think my original point is valid.

1 Like

For context, one of the reasons to allow defaults in the middle is so that the parameter at the end can be a trailing closure.

5 Likes

Congrats on your first pitch!

A lot of times, it's nice for the consumer to explicitly consider whether they want to pass nil or a value. However this proposal would automatically enable a default behaviour that I won't be able to opt out of.

If you’re talking about “automatic behaviour” as in Xcode autocomplete, it’d autocomplete with all variants of a method, just as it does today when = nil is specified on an optional parameter.

-W

I think the point @rounak is making is that if the behavior is to omit the default value and have = nil be implicit in the function signature, there would be no way for an API author to specify an Optional parameter which may not be omitted.

2 Likes

Yes me too, it seems like a very small win at the cost of an entirely alien concept, variables that automatically defined. Are there any other examples of that in Swift.

Yes I mention one in the pitch, if you type

var foo: Int?

It’s initialized to nil. This is the equivalent.

Yes but that is what we are talking about, we think this should not be in the language. Well at least I do.

2 Likes

I guess my point is that in the vast majority of cases this is the default behavior I’d want, so I’d rather there be an annotation for the rare case that the API designer would require an optional than have all the Obj-C APIs stay ugly.

But I understand your point and that your priorities are different.

-W

I was more commenting on the fact that your pitch as written offers no suggestion for how to recover the current behavior if an API designer wishes. The current behavior offers the ability to offer Optional parameters which may be omitted or required based on the designer's use case, but the new behavior would take away that option. What sort of syntax would you expect for a required Optional parameter?

I think the current behavior is a left over from when Implicit unwrapped optional were a different construct than regular optional. I filed this bug report:
https://bugs.swift.org/browse/SR-10931

Wow I hadn't tried all of those, that is quite inconsistent!

Oh interesting. Let me throw out another variation to consider: maybe only __nullable arguments in c functions should get the "default to nil" treatment in the clang importer? This has several nice features: it doesn't make keyword arguments magically vanish (because they don't exist for c functions) and the c functions are the least likely to be audited.

Disadvantage/tuning required on this: if the argument isn't the last argument, then this gets really weird. Maybe this should only apply to nullable arguments at the end of the arg list?

-Chris

I don't think fixing a relatively minor issue with some apparently-neglected APIs would justify this sort of extremely broad importer change. As you said yourself, UTTypeCreatedPreferredIdentifierForTag is a bad API from a Swift perspective on more dimensions than just the final argument, and that's true of most CF-style APIs. If you want to work with a Swiftier API for this framework, you should probably write a tiny wrapper library around it.

A default-argument attribute / apinote is an interesting idea, though of course it doesn't solve your specific problem of working with other people's APIs.

I certainly don't think we want a general rule that optional arguments implicitly default to nil.

2 Likes

I’d love to see someone pitch and drive a proposal to remove that behavior, by the way. Optionals are the only type in Swift that can be default initialized in this manner, and it feels like an unnecessary bit of magic to me.

18 Likes

Well, it seems like most people on here don’t like the idea of optionals defaulting to nil in general, which I disagree with but also I’m not willing to die on that hill. (For the record I think it’s not ‘magic’ because for an optional there really is one default value that completely makes sense, always.)

So I'll reverse course and support adding some kind of attribute to clang (let’s call it __null_by_nature for argument’s sake) that could be put in C and Obj-C APIs, in the same form as the nullable properties (eg, one could turn it on for an entire file but call out exceptions, but the default would be to have it off and add __null_by_nature per-method / function).

Thanks for your feedback on this issue! Hopefully my next pitch will do better.

-W

-1 from me.

Giving a default value auto-magically is so not swift-y. It's ambiguous and could lead onto hard to find bugs. It should be the function author's responsibility whether to give it a nil default value or not.