Reputation: 176
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
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