skip to Main Content

I was just experimenting with some Swift code samples and by making a mistake I’ve found our very weird behaviour (to me) that I don’t understand.

I’ve defined this function:

func makeIncrementer(number: Int) -> ((Int) -> Int) {
  func incrementer(inputNumber: Int) -> Int {
    return inputNumber+1
  }
  return incrementer
}

*yes, the parameter number in not used, that was unintentional mistake, but lead to finding out this weird behaviour I’m asking now.

Then I called the code:

let functionVariable = makeIncrementer(number: 7)
print(functionVariable)
print(functionVariable(7))

which resulted in this output:

(Function) 
8

after this I realized that the number parameter in makeIncrementer function does not make sense, so I’ve deleted the parameter in makeIncrementer invocation, but xCode didn’t show any error message. So I just tried to rebuild this:

let functionVariable = makeIncrementer(number: )
print(functionVariabl
print(functionVariable(7))

And I’ve received this output:

(Function)
(Function)

Here are my questions:

  1. How is it possible it can be built? Parameter number is not optional, or is it?
  2. Even if the parameter number would be optional, how can it result in two objects that are type of function?

Thank you very much for a explanation

2

Answers


  1. In your second example you aren’t calling the function, but assigning it to the variable using its overload identifier. This is also why it is printing (Function) twice; the first is the original function, the second is the returned curried function.

    Here is an example defining an overload for your function that accepts a String showing that let functionVariable1 = makeIncrementer(number:) is assigning the specific overload of your function that accepts an Int to the variable. Calling this variable functionVariable1(4) now no longer needs (and won’t accept) a parameter label, and returns your curried function. Thus, calling print(functionVariable1(4)(11)) will now print the input + 1 as expected.

    func makeIncrementer(number: Int) -> ((Int) -> Int) {
        func incrementer(inputNumber: Int) -> Int {
            return inputNumber + 1
        }
        return incrementer
    }
    
    func makeIncrementer(string: String) -> ((Int) -> Int) {
        func incrementer(inputNumber: Int) -> Int {
            return inputNumber + 1
        }
        return incrementer
    }
    
    let functionVariable1 = makeIncrementer(number:)
    print(functionVariable1)
    print(functionVariable1(4)(11))
    // no error because the overload expecting an Int is assigned to functionVariable1
    
    let functionVariable2 = makeIncrementer(string:)
    print(functionVariable2)
    print(functionVariable2("string")(11))
    // no error because the overload expecting a String is assigned to functionVariable2
    

    For function definitions that accept more than one parameter you can list parameter labels sequentially to assign to a variable, this also removes the need for labels in later calls.

    func fn(number: Int, string: String) {
        print("number: (number)")
        print("string: (string)")
    }
    
    let assigneOverload = fn(number: string:)
    assigneOverload(1, "swift")
    
    Login or Signup to reply.
  2. This code

    let functionVariable = makeIncrementer(number: )
    

    causes functionVariable to point to your makeIncrementer(number:) function, not to a call to that function. (That syntax is a function signature, not a call to a function.

    If you then execute this code:

    print(incrementer(7)(3))
    

    You’ll tell incrementer to give you its result function (With a throw-away value of 7), and then pass that function the value 3. Thus the result will be to print the value 4.

    you should declare your code like this:

      func incrementer(_ inputNumber: Int) -> Int {
        return inputNumber+1
      }
      return incrementer
    }
    
    let incrementer = makeIncrementer()
    print(incrementer(3))
    

    That does what you intend: In the line let incrementer = makeIncrementer() you are calling makeIncrementer(), and it is returning an incrementer function.

    The output of print(incrementer(3)) will be to print "4" as you are expecting.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search