Allow parameters to default to the value of earlier parameters

Possibly related to this pitch. Here's an example of a utility initializer for a view:

init(title: String, accessibilityTitle: String? = nil) {
    self.title = title
    self.accessibilityLabel = accessibilityTitle ?? title
}

It would be a nice little bit of cleanup to be able to pass the value of the title parameter to the later accessibilityTitle parameter by default:

init(title: String, accessibilityTitle: String = title) {
    self.title = title
    self.accessibilityLabel = accessibilityTitle
}

In general, I think any function signature where an early parameter is overridden by a later parameter could benefit from this tweak.

8 Likes

There have been several discussion on this, I believe.

The issue, IMO, is that there is no limiting principle. By this I mean, suppose we permit = title. Shouldn’t we also permit = "Title: \(title)"? And also = title + " " + altText? And why not any arbitrary expression?

Taken to its logical end, this ends up being pure sugar for code that you can write within the body of the function, so long as you don’t try to reference arguments that follow the current argument. It doesn’t seem like this would improve readability or safety, so it doesn’t seem like an overall win to me.

2 Likes

This also has the complication that Swift has no model for side-effect-free/“pure” functions at the moment. Presumably we would not want default values to allow side effects.

4 Likes

Why indeed?

The same argument can be made for default parameters: it's just sugar. The proposed features covers "second-tier" defaults as well, getting rid of the same bloat (optional + if/guard to check and set) that default parameters to away with for "first-tier" defaults.

No. First, because the bar for adding new sugar is much higher than that for keeping existing ones. Second, because to be able to use “Optional + check-and-set,” you need to be able express some sort of default at all in the first place.

I will add that some kind of default arguments is also needed to get the #file, #line and other compiler supplied placeholders to work for diagnostic functions.

Arbitrary code with side effects is already allowed. I can get this nonsense to compile:

func test(_ t: Void = FileManager.setDefaultPlaceholder(nil, forMarker: nil, withBinding: .alignment)) {
	/* ... */
}

You can call functions in default values, and you can use operators. You just can't reference self or other parameters of the current function.

If some day we add the concept of a pure function, we'll need to restrict default values of pure functions to a pure expression (something I need to add in my exploratory proposal), but I think that ship has already sailed for regular (non-pure) functions.

4 Likes

Not really; you can have them call-site (see e.g. Java). That's what we sugar away with default parameters.

1 Like

Not in the general case. At the call site, the user may not be able to obtain or initialize an instance of that type.

Default arguments are inlined code as of Swift 4. That doesn’t mean they can’t call things that are internal-but-ABI, but it’s not going to be the usual thing. As @dabrahams has pointed out in the past, a default that the user can’t specify explicitly still has to be documented, and is kind of a jerk move anyway.

3 Likes

I just found out that Kotlin allows you to do this, and now I want it all over again. Has anything changed on this front?

Example adapted from a Kotlin snippet I just saw:

fun showError(
    error: MyErrorType,
    message: String = error.getString(R.string.i_dont_actually_know_kotlin)) {
1 Like

I just ran into a scenario where this would be useful and thought I would look it up.
Any update or solid arguments against this seeing how other languages already have the ability to do it?

Example:

func configureButton(
titleColor: UIColor, 
titleForHightlightedState: UIColor = titleColor, 
titleForDisabledState: UIColor = titleColor
)

Instead of making arguments optional and then performing a check inside, why not have this included in the signature?

2 Likes

In the four years since I opened this thread, I’ve had a handful of times when I wanted this. Definitely still in favor of making it possible.

I think that, since I started this thread, there was a change where default argument values are available in the public interface of functions. It feels like that would bring us closer to being able to do this, no?

3 Likes

I recently found myself wanting this as well, and posted this thread. Wasn’t able to find a previous discussion but glad this got surfaced again!

The discussion there goes into the some of the problems this feature would have to contend with w.r.t. the current model for default arguments.

2 Likes