Switch expression function I made a bunch of functions and an enumeration, that together allow me to write something like a switch expression. It's not as powerful as Swift switch statements, since it's lacking pattern matching and I don't intend to use this in real code, it was just an experiment. Here is what I got:

enum Caze&lt;T: ForwardIndexType where T: Equatable&gt; {
    case RangeCaze(Range&lt;T&gt;)
    case ArrayCaze([T])

    func contains(elem: T) -&gt; Bool {
        switch self {
        case let .RangeCaze(r):
            return r.contains(elem)
        case let .ArrayCaze(arr):
            return arr.contains(elem)
        }
    }
}


func caze&lt;T: ForwardIndexType, R where T: Equatable&gt;(vals: T..., @autoclosure(escaping) ret f: () -&gt; R) -&gt; (Caze&lt;T&gt;, () -&gt; R) {
    return (.ArrayCaze(vals), f)
}

func caze&lt;T: ForwardIndexType, R where T: Equatable&gt;(vals: Range&lt;T&gt;, @autoclosure(escaping) ret f: () -&gt; R) -&gt; (Caze&lt;T&gt;, () -&gt; R) {
    return (.RangeCaze(vals), f)
}

func caze&lt;T: Equatable, R&gt;(vals: T..., @autoclosure(escaping) ret f: () throws -&gt; R) -&gt; ([T], () throws -&gt; R) {
    return (vals, f)
}


func schwitch&lt;T: ForwardIndexType, R where T: Equatable&gt;(value: T, _ cases: (Caze&lt;T&gt;, () -&gt; R)..., @autoclosure def: () throws -&gt; R) rethrows -&gt; R {
    for (vals, f) in cases {
        if vals.contains(value) {
            return f()
        }
    }
    return try def()
}

func schwitch&lt;T: Equatable, R&gt;(value: T, _ cases: ([T], () -&gt; R)..., @autoclosure def: () throws -&gt; R) rethrows -&gt; R {
    for (vals, f) in cases {
        if vals.contains(value) {
            return f()
        }
    }
    return try def()
}


This allows me to write code like:

schwitch(5, // results in "lol"
    caze(0, ret: "hello"),
    caze(1, 2, ret: "test"),
    caze(3..&lt;7, ret: "lol"),
    def: "nop")

schwitch("helloo", //results in "nop"
    caze("hello", "Hello", ret: "test"),
    def: "nop")


I think there are a few problems with this though.


There is quite a bit of code duplication due to a few nearly identical functions being needed.
The closure sent to the caze functions are escaping, though they are intended to never actually escape beyond a very defined scope.
If code in a caze function throws, it doesn't get rethrown.
I also considered an alternative implementation for the schwitch functions but am worried that it takes brevity a bit too far:

(cases.filter{$0.contains(value)}.first ?? def)()



Are there any ways to improve on these 4 points and are there any other things that I missed or could have done better?
There is quite a bit of code duplication due to a few nearly identical functions being needed.
  


This is probably the biggest issue and the one I'll be addressing here.

The two schwitch functions have identical bodies, this is a major code smell. The only difference between the two is the generic constraints on T and the type T is wrapped up in (Array and Caze repectively). You don't actually care that Tconforms to ForwardIndexType in the schwitch function and the only way I was using both Caze and Array was by calling contains on them (with identical signatures). This clearly calls for a protocol. And I didn't even need to declare one myself. the contains function I was using is declared in SequenceType, a protocol both Array and Range conform to. So here's what the new (and only) schwitch function will look like:

func schwitch&lt;S: SequenceType, R where S.Generator.Element: Equatable&gt;(value: S.Generator.Element, _ cases: (S, () -&gt; R)..., @autoclosure def: () -&gt; R) -&gt; R {
    for (vals, f) in cases {
        if vals.contains(value) {
            return f()
        }
    }
    return def()
}


You will notice that function is now missing a rethrows, the swift compiler hangs up on that due to a bug.

This also allowed me to get rid of the Caze enum and only have two caze functions, one that takes any amount of values and one that takes a range:

func caze&lt;T: Equatable, R&gt;(vals: T..., @autoclosure(escaping) ret f: () -&gt; R) -&gt; (AnySequence&lt;T&gt;, () -&gt; R) {
    return (AnySequence(vals), f)
}

func caze&lt;T, R where T: Equatable, T: ForwardIndexType&gt;(range: Range&lt;T&gt;, @autoclosure(escaping) ret f: () -&gt; R) -&gt; (AnySequence&lt;T&gt;, () -&gt; R) {
    return (AnySequence(range), f)
}


I've made both functions return an AnySequence&lt;T&gt; instead of more concrete type, I think that makes sense, considering how the results are used, but it's really up to you if you maybe want to return Array&lt;T&gt; and Range&lt;T&gt; instead.

I can still use my function exactly as I did before.