rodalfus
rodalfus

Reputation: 176

Segmentation Fault 11 when compiling swift file with enum in Xcode

When trying to compile a Swift file such as this one (as part of a project), Xcode (Version 7.3.1) throws a segmentation fault 11 while emitting SIL for 'operationForOperationType'

import Foundation

enum OperationType: String{
    case Addition = "∑"

    func operationForOperationType() -> ([Double], [[Double]]? -> Double){
        switch self {
            case OperationType.Addition:
                return {$0.reduce(0, combine: {$0 + $1})}
        }
    }
}

Is this a compiler bug or actually the result of the given code? Other variations of the code (more than one case, switch on a given OperationType instead of self) also resulted in a segmentation fault 11.

Edit: Remove .output (a copy-paste-error)

Edit II: The function's purpose is to return a closure for a given OperationType. For example, if my OperationType is addition, I want it to return the closure that adds elements in the array. This, of course, is a simplification. It might occur, that I want a closure to be returned, which combines elements in the array and a two dimensional array (think matrix-vector multiplication with a later dot-product).

Usage may be, for example:

var op = OperationType.Addition
let f = op.operationForOperationType()
let arr: [Double] = [1, 5, 2]
f(arr, nil)
//-> 8

Upvotes: 1

Views: 730

Answers (1)

luk2302
luk2302

Reputation: 57184

First off: if the compiler is crashing you might want to submit a bug report to apple.

Secondly regarding your code: Took me a while to figure out what is wrong here! Your declared return type is not a closure!

func operationForOperationType() -> ([Double], [[Double]]? -> Double) {

This line means the function returns a tuple of one [Double] and one closure of type [[Double]]? -> Double. It does not return a closure whose inputs are [Double] and [[Double]]? and returns a Double.

To correct the return type to actually specify to return just a closure you have to write:

func operationForOperationType() -> ([Double], [[Double]]?) -> Double {

Note the moved closing )!

Now we can get to the actual implementation of the return value:

func operationForOperationType() -> ([Double], [[Double]]?) -> Double {
    switch self {
    case OperationType.Addition:
        return { (a, b) in a.reduce(0, combine: {$0 + $1})}
    }
}

Since we defined the input to be of type ([Double], [[Double]]?), a tuple, we have to either access those parameters via $0.0 and $0.1 or we write (a, b) in to map the first tuple value to a and the second to b.

Now everything compiles. I still do not know what you want to do with b, but that is none on my business ;)

Putting it all together:

enum OperationType: String{
    case Addition = "∑"

    func operationForOperationType() -> ([Double], [[Double]]?) -> Double {
        switch self {
        case OperationType.Addition:
            return { (a, b) in a.reduce(0, combine: {$0 + $1})}
        }
    }
}

var op = OperationType.Addition
let f = op.operationForOperationType()
let arr: [Double] = [1, 5, 2]
f(arr, nil) // actually outputs 8 now

Upvotes: 1

Related Questions