1

I'm very new to Swift, but slowly learning by following the Stanford iTunes U course. I have a question about storing and calling functions in an array.

The code I have (below) seems to store the function properly, but when I try to call one of the functions I get this error: '(IntegerLiteralConvertible, IntegerLiteralConvertible) -> $T6' is not identical to (String, Op).

I found this answer that was helpful in getting to where I am, but now I'm stuck.

enum Op {
    case binary((Double, Double) -> Double)
}

var ops = [String: Op]()

func addOperation(symbol: String, op: Op) {
    ops[symbol] = op
}

addOperation("×", Op.binary(*))
addOperation("÷", Op.binary({ $1 / $0 }))
addOperation("+", Op.binary(+))
addOperation("−", Op.binary({ $1 - $0 }))

var newValue = ops["÷"](6, 3) // Produces the error

My understanding was that ops["÷"] should be the function I stored in the array earlier. Am I not calling it properly?

2 Answers 2

4

@Nate Cook answer is corret but why do you have to use enum in this case? Consider using typealias like following :

var ops = [String: Op]()

    func addOperation(symbol: String, op:Op) {
        ops[symbol] = op
    }

    addOperation("×", (*))
    addOperation("÷", ({ $1 / $0 }))
    addOperation("+", (+))
    addOperation("−", ({ $1 - $0 }))

    var newValue = ops["÷"]?(3,6)

// you have to put this outside of any class
public typealias Op = (Double, Double) -> Double
Sign up to request clarification or add additional context in comments.

3 Comments

Sorry, didn't see your post come in! Good idea ;)
Is there any advantage to using an enum?
@Phil An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code. In your case enum hold a single value only thats why you should consider using typealias
3

You have two problems there. First, subscripting a dictionary returns an optional value, so ops["÷"] is an Op? that needs to be unwrapped before you can use it.

Second, the associated value of an enum can't be accessed directly—you can only get the value when pattern matching in a switch statement. I'd suggest adding a computed property to Op that does the work for you:

enum Op {
    case binary((Double, Double) -> Double)

    var binaryCall: ((Double, Double) -> Double)? {
        switch self {
        case let .binary(operation):
            return operation
        }
    }
}

Then you would call it like this instead:

var newValue = ops["÷"]?.binaryCall?(6, 3)
// Optional(0.5)

An alternate method of implementation would be to just build an dictionary of binary operations, like so (you still need to unwrap once, though):

typealias BinaryOp = (Double, Double) -> Double

var binaryOps: [String: BinaryOp] = [:]

binaryOps["×"] = { $0 * $1 }
binaryOps["÷"] = { $1 / $0 }

newValue = binaryOps["÷"]?(6, 3)

1 Comment

Thanks for the explanation of my errors, @Nate Cook. I really appreciate it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.