Могу ли я использовать функцию, хранящуюся в переменной, в качестве оператора в Swift?

В Swift мне интересно определить пользовательский оператор, чью реализацию я могу изменить в зависимости от контекста. В основном, я хотел бы сделать это:

infix operator <-> {} // define the operator <->

Затем, в какой-то момент в моем коде:

let <-> : (Int, Int) -> Int = (+)  // say that here, <-> means +
2 <-> 5 // obtain 7

Я все еще хочу иметь возможность определить <-> иначе (и, возможно, для других типов аргументов) в некоторых других частях кода. И я не хочу заявлять funcs, так как назначенная функция сама будет исходить из вызова внешней функции.

В Swift 1.2 это происходит с ошибкой "Ожидаемый шаблон" в определении <-> постоянная.

Что я делаю неправильно? Какие есть альтернативы?

2 ответа

Решение

Лучшее, что я могу придумать, это что-то вроде:

infix operator <-> {} // define the operator <->

func <-> (lhs:Int, rhs:Int) -> Int {
    return arrowFunction(lhs, rhs)
}

let arrowFunction : (Int, Int) -> Int = (+)

println("\(2 <-> 7)")

Я чувствую, что вы пытаетесь достичь с let в первую очередь не следует ожидать, что связывание сработает (хотя и согласуется с остальной частью Swift)... Я не знаю достаточно теории PL, чтобы правильно выразить свое мнение, но что-то вроде того, что когда вы объявляете имя с let или же varВы заранее указываете тип (и тип остается неизменным после того, как вы его объявили), но здесь вы не знаете фактический тип, пока аргументы не будут фактически переданы.

Это не отвечает на ваш вопрос, но - если вам нужна синтаксическая сладость - вот некоторый код, который я придумал, который позволяет вам "инфиксировать" функции. (Хотя на самом деле это не проверялось, вам, возможно, потребуется настроить прецеденты и что-то еще. Это более насмешливо, чем все остальное.)

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
Другие вопросы по тегам