Reputation: 59994
In Swift, I'm interested in defining a custom operator whose implementation I may want to change depending on the context. Basically, I'd like to do this:
infix operator <-> {} // define the operator <->
Then, at some point in my code:
let <-> : (Int, Int) -> Int = (+) // say that here, <-> means +
2 <-> 5 // obtain 7
I still want to be able to define <->
differently (and, possibly, for other argument types) in some other parts of the code. And I don't want to declare func
s, as the assigned function will itself actually come from an external function call.
In Swift 1.2, this fails with the error “Expected pattern” in the definition of the <->
constant.
What am I doing wrong? What are the alternatives?
Upvotes: 0
Views: 192
Reputation: 1817
I feel what you're trying to achieve with a let
binding shouldn't in the first place be expected to work (while being consistent with the rest of Swift)... I don't know enough PL theory to express my view properly, but something along the lines that when you declare a name with let
or var
, you specify the type beforehand (and the type stays fixed once you've declared it), but here you don't know the actual type until the arguments are actually passed.
This doesn't answer you question but - if it's syntactic sweetness you're after - here's some code I came up with that kind of allows you to "infixify" functions. (Haven't really tested it though, you might need to tweak the precedences and what-not. It's more tongue-in-cheek than anything else.)
func ~<T, U, V>(left: T, f: (T, U) -> V) -> (U -> V) {
return { y in f(left, y) }
}
func ~<U, V>(g: U -> V, right: U) -> V {
return g(right)
}
var plus = {(a: Int, b: Int) in a + b }
2~plus~2 // 4
[1, 2, 3, 4, 5, 7, 8]~contains~{$0 == 6} // false
let dot: ([Double], [Double]) -> Double = { v1, v2 in
return reduce(lazy(Zip2(v1, v2)).map(*), 0, +)
}
func dot: ([Int], [Int]) -> Int {
return 0 // "fake" dot product
}
[1, 2, 3, 4]~dot~[2, 3, 4, 5] // 0
[1.0, 2, 3, 4]~dot~[2, 3, 4, 5] // 40.0
Upvotes: 1
Reputation: 41226
The best I can come up with is something like:
infix operator <-> {} // define the operator <->
func <-> (lhs:Int, rhs:Int) -> Int {
return arrowFunction(lhs, rhs)
}
let arrowFunction : (Int, Int) -> Int = (+)
println("\(2 <-> 7)")
Upvotes: 1