Swift - как создать пользовательские операторы для использования в других модулях?
Я создал образец проекта и структуру рядом с ним. Структура называется "SampleFramework". Затем я создал пользовательский оператор в SampleFramework. Вот как это выглядит:
infix operator >>= {associativity left}
public func >>=<A, B>(a: A?, f: A -> B?) -> B? {
if let a = a { return f(a) }
else { return .None }
}
Тогда я хотел использовать это основное приложение. Я импортировал SampleFramework
в свой исходный файл, а затем я написал этот код, чтобы проверить его:
NSURL(string: "www.google.com") >>= { println("\($0)") }
Он не компилировался. Вот сообщение об ошибке Xcode:
Неоднозначные операторные объявления, найденные для оператора. Оператор не является известный бинарный оператор
Ответы
Ответ 1
Я понял это. Я думаю, что объявление оператора (infix operator >>= {associativity left}
) является специфичным для модуля. Вы не можете применять к нему контроль доступа. Но функциональную функцию можно получить в других модулях. Поэтому для выполнения этой работы мне пришлось скопировать объявление оператора и вставить его в основной проект.
Ответ 2
Я могу подтвердить, что то, что вы видите, действительно происходит. Я просто пробовал это сам, и я видел тот же результат.
Мое мнение состоит в том, что >>=
как-то конфликтует с каким-либо другим оператором (вероятно, оператор сдвига смещения: >>
) или объявляется где-то еще (вы можете понять, почему я думаю, что здесь). Я сделал успешно объявленные пользовательские операторы в фреймворке и использовал их в главном коде приложения (вы можете видеть, что здесь например).
Я бы предложил переименовать ваш пользовательский оператор в другое. Когда я это сделал (переименовал пользовательский оператор в >>>=
), компилятор прекратил жаловаться, и мое приложение скомпилировано просто отлично.
Позже отредактируйте
Ok. Так что это может помочь немного больше. В основном, когда оператор уже объявлен, и вы хотите добавить дополнительные функции к этому оператору (например, делать такие вещи, как 3 * "Hello"
, например Johan Kool, он хотел) всех вас необходимо выполнить перегрузку, что операторный метод.
В принципе, в вашем конкретном случае я теперь на 100%, что >>=
- уже объявленный оператор, и вы можете продолжить и просто добавить эти строки в свою структуру:
public func >>=<A, B>(a: A?, f: A -> B?) -> B? {
if let a = a { return f(a) }
else { return .None }
}
Это заставит вашего оператора работать. НО он наследует приоритет и ассоциативность исходного оператора, что дает вам меньше контроля над тем, как он должен себя вести.
Ответ 3
Кажется, достаточно просто добавить
infix operator + : Additive
в каждом источнике, где вы хотите применить свой оператор, определенный каркасом, при условии, что ваша инфраструктура имеет несколько
public func + (lhs: ...
объявлена.
Во всяком случае, это неприятно иметь необходимость добавить это, если вы используете фреймворк, и я хотел бы увидеть какой-то способ иметь какой-то глобальный подход, при котором импорт фреймворка также автоматически предоставляет операторам.
Изменить. После долгих часов работы проблема исчезла. Я не понял, в чем причина. У меня было много объявлений infix
в моей базовой структуре (по исторической причине). Как только я избавился от них, все стало нормально. Итак, теперь, когда у меня есть только infix
для новых операторов, это нормально. Но, очевидно, повторное объявление существующих (например, *
, +
и т.д.). Swift, похоже, получает подсказки.