Default optional parameter in Swift function

SwiftFunctionOptional

Swift Problem Overview


When I set firstThing to default nil this will work, without the default value of nil I get a error that there is a missing parameter when calling the function.

By typing Int? I thought it made it optional with a default value of nil, am I right? And if so, why doesn't it work without the = nil?

func test(firstThing: Int? = nil) {
    if firstThing != nil {
        print(firstThing!)
    }
    print("done")
}
test()

Swift Solutions


Solution 1 - Swift

Optionals and default parameters are two different things.

An Optional is a variable that can be nil, that's it.

Default parameters use a default value when you omit that parameter, this default value is specified like this: func test(param: Int = 0)

If you specify a parameter that is an optional, you have to provide it, even if the value you want to pass is nil. If your function looks like this func test(param: Int?), you can't call it like this test(). Even though the parameter is optional, it doesn't have a default value.

You can also combine the two and have a parameter that takes an optional where nil is the default value, like this: func test(param: Int? = nil).

Solution 2 - Swift

The default argument allows you to call the function without passing an argument. If you don't pass the argument, then the default argument is supplied. So using your code, this...

test()

...is exactly the same as this:

test(nil)

If you leave out the default argument like this...

func test(firstThing: Int?) {
    if firstThing != nil {
        print(firstThing!)
    }
    print("done")
}

...then you can no longer do this...

test()

If you do, you will get the "missing argument" error that you described. You must pass an argument every time, even if that argument is just nil:

test(nil)   // this works

Solution 3 - Swift

Swift is not like languages like JavaScript, where you can call a function without passing the parameters and it will still be called. So to call a function in Swift, you need to assign a value to its parameters.

Default values for parameters allow you to assign a value without specifying it when calling the function. That's why test() works when you specify a default value on test's declaration.

If you don't include that default value, you need to provide the value on the call: test(nil).

Also, and not directly related to this question, but probably worth to note, you are using the "C++" way of dealing with possibly null pointers, for dealing with possible nil optionals in Swift. The following code is safer (specially in multithreading software), and it allows you to avoid the forced unwrapping of the optional:

func test(firstThing: Int? = nil) {
    if let firstThing = firstThing {
        print(firstThing)
    }
    print("done")
}
test()

Solution 4 - Swift

You are conflating Optional with having a default. An Optional accepts either a value or nil. Having a default permits the argument to be omitted in calling the function. An argument can have a default value with or without being of Optional type.

func someFunc(param1: String?,
          param2: String = "default value",
          param3: String? = "also has default value") {
    print("param1 = \(param1)")

    print("param2 = \(param2)")

    print("param3 = \(param3)")
}

Example calls with output:

someFunc(param1: nil, param2: "specific value", param3: "also specific value")

param1 = nil
param2 = specific value
param3 = Optional("also specific value")

someFunc(param1: "has a value")

param1 = Optional("has a value")
param2 = default value
param3 = Optional("also has default value")

someFunc(param1: nil, param3: nil)

param1 = nil
param2 = default value
param3 = nil

To summarize:

  • Type with ? (e.g. String?) is an Optional may be nil or may contain an instance of Type
  • Argument with default value may be omitted from a call to function and the default value will be used
  • If both Optional and has default, then it may be omitted from function call OR may be included and can be provided with a nil value (e.g. param1: nil)

Solution 5 - Swift

in case you need to use a bool param, you need just to assign the default value.

func test(WithFlag flag: Bool = false){.....}

then you can use without or with the param:

test() //here flag automatically has the default value: false
test(WithFlag: true) //here flag has the value: true

Solution 6 - Swift

"Optional parameter" means "type of this parameter is optional". It does not mean "This parameter is optional and, therefore, can be ignored when you call the function".

The term "optional parameter" appears to be confusing. To clarify, it's more accurate to say "optional type parameter" instead of "optional parameter" as the word "optional" here is only meant to describe the type of parameter value and nothing else.

Solution 7 - Swift

If you want to be able to call the func with or without the parameter you can create a second func of the same name which calls the other.

func test(firstThing: Int?) {
    if firstThing != nil {
        print(firstThing!)
    }
    print("done")
}

func test() {
    test(firstThing: nil)
}

now you can call a function named test without or without the parameter.

// both work
test()
test(firstThing: 5)

Solution 8 - Swift

Don't let the question mark fools you!

Optional is an enum which has two cases:

@frozen public enum Optional<Wrapped> : ExpressibleByNilLiteral {

    /// The absence of a value.
    ///
    /// In code, the absence of a value is typically written using the `nil`
    /// literal rather than the explicit `.none` enumeration case.
    case none

    /// The presence of a value, stored as `Wrapped`.
    case some(Wrapped)
}

code from the original compiled source of the Optional inside Xcode


When you are defining a function that accept some Type of arguments, you can pass a default value withe the same type.

in your case

the type of the firstThing is Optional<Int> (also known as Int?). So if you want the caller to the oportunity to ignore the paramter, you MUST do the job for the caller and pass a default value.

Usually we need the .none case of the optional so we can do:

func test(firstThing: Optional<Int> = .none) { ... }

This is exactly the same as:

func test(firstThing: Int? = nil) { ... }

Also!

Who seys that we the default value of an optional is a nil? maybe passing nil means that the function should remove something by updating it's value to 'nil'. So don't asume "the default value for optional is a nil"

Solution 9 - Swift

It is little tricky when you try to combine optional parameter and default value for that parameter. Like this,

func test(param: Int? = nil)

These two are completely opposite ideas. When you have an optional type parameter but you also provide default value to it, it is no more an optional type now since it has a default value. Even if the default is nil, swift simply removes the optional binding without checking what the default value is.

So it is always better not to use nil as default value.

Solution 10 - Swift

Default value doesn't mean default value of data type .Here default value mean value defined at the time of defining function. we have to declare default value of variable while defining variable in function.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRickBrunstedtView Question on Stackoverflow
Solution 1 - SwiftEmilioPelaezView Answer on Stackoverflow
Solution 2 - SwiftAaron RasmussenView Answer on Stackoverflow
Solution 3 - SwiftnbloqsView Answer on Stackoverflow
Solution 4 - SwiftChuck KrutsingerView Answer on Stackoverflow
Solution 5 - SwiftNiib FoudaView Answer on Stackoverflow
Solution 6 - SwiftTodanleyView Answer on Stackoverflow
Solution 7 - SwiftSean256View Answer on Stackoverflow
Solution 8 - SwiftMojtaba HosseiniView Answer on Stackoverflow
Solution 9 - SwiftShubham NaikView Answer on Stackoverflow
Solution 10 - SwiftMahesh KulkarniView Answer on Stackoverflow