1
struct CalculatorBrain {
    private var accumulator: Double?
    func changeSign(operand: Double) -> Double {
        return -operand
    }

    private enum Operation {
        case constant(Double)
        case unaryOperation((Double) -> Double)
    }
    private var operations: Dictionary<String,Operation> = [
        "π" : Operation.constant(Double.pi),
        "√" : Operation.unaryOperation(sqrt),
        "±" : Operation.unaryOperation(changeSign) /* Cannot convert value of type '(CalculatorBrain) -> (Double) -> Double' to expected argument type '(Double) -> Double'  */
    ]
}

I am getting the error message on the line starting with "±". I looked up a solution online and here are the similar questions & potential solutions I found below. But I don't quite understand what's going on. Can anyone help?

Similar Question + solution (1)

Similar Question + Solution (2)

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
Yves
  • 87
  • 6

2 Answers2

2

The changeSign function is an instance function of CalculatorBrain.

In Swift, any function bound to an instance of an object actually has the type (Type) -> (Arguments) -> ReturnType, instead of just (Arguments) -> ReturnType.

If you're writing code like instance.doStuff(arguments), what is actually happening in the background is a partial application Type.doStuff(instance)(arguments). Type.doStuff(instance) returns your instance function that you then can call using its normal arguments.

As you are creating the operations dictionary directly within the struct and not within a function or initializer of it, Swift only has access to static members of your type so instead of changeSign being bound to an instance of CalculatorBrain, you are getting the unbound CalculatorBrain.changeSign method.

That is why your function shows up as (CalculatorBrain) -> (Double) -> Double instead of just (Double) -> Double.

To fix this, make the method static, so it removes the partial application with an instance of CalculatorBrain, declare the function as a global function or define operations in an initializer of CalculatorBrain (though you might have trouble accessing instance members before finishing instantiation when using the last approach).

Palle
  • 11,511
  • 2
  • 40
  • 61
0

Try changing changeSign to static.

The non-static function will have an implicit "self" argument and thus not match the (Double) -> Double you are after.

Samah
  • 1,224
  • 2
  • 13
  • 15