Подтвердить что ты не робот

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:

Неоднозначные операторные объявления, найденные для оператора. Оператор не является известный бинарный оператор

4b9b3361

Ответ 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, похоже, получает подсказки.