Я хочу создать два оператора настраиваемого диапазона: <..
, <.<
<..
..<
.infix operator <.. : RangeFormationPrecedence
public func <.. (lhs: Int, rhs: Int) -> Range {
return lhs - 1 ... rhs
}
Примечание: Я также узнал о дополнительных 22 ошибках компиляции, связанных с фактическим объявлением самого настраиваемого оператора (<..
).
for i in 1<..9 {
print(i, terminator: " ")
}
// Prints "0 1 2 3 4 5 6 7 8 9"
<.<
<..
и ..<
infix operator <.< : RangeFormationPrecedence
public func <.< (lhs: Int, rhs: Int) -> Range {
return lhs - 1 ..< rhs
}
Примечание: Я также узнал о дополнительных 22 ошибках компиляции, связанных с фактическим объявлением самого настраиваемого оператора (<.<
).
for i in 1<.<10 {
print(i, terminator: " ")
}
// Prints "0 1 2 3 4 5 6 7 8 9"
Как я могу этого добиться?
Кроме того, какой тип Range
я должен возвращать?
Наконец, есть ли какие-либо предварительные условия, которые необходимо добавить к самим операторам настраиваемого диапазона для обеспечения безопасности?
Я решил создать два оператора (1x постфиксный, 1x инфиксный) для достижения одной из этих целей:
postfix operator <
public postfix func < <T: Numeric>(n: T) -> T { return n - 1 }
infix operator .< : RangeFormationPrecedence
public func .< <T: Numeric>(lhs: T, rhs: T) -> CountableRange<T> {
return lhs ..< rhs
}
Тогда я могу:
for i in 1<.<10 {
print(I, terminator: " ")
}
//Prints "0 1 2 3 4 5 6 7 8 9"
Предостережение: У меня не может быть пробела между числами и операторами (т.е. 1 <.< 10
)
Что именно не работает?
Только что обновил вопрос @BallpointBen
<..
и <.<
не являются допустимыми идентификаторами для операторов. Вы найдете
подробности в Операторы в справочнике по языку Swift.
Имитация декларации существующих
extension Strideable where Self.Stride : SignedInteger {
public static func ... (minimum: Self, maximum: Self) -> CountableClosedRange<Self>
}
оператор, ваш первый пользовательский оператор может быть реализован как
infix operator <!! : RangeFormationPrecedence
extension Strideable where Self.Stride : SignedInteger {
public static func <!! (minimum: Self, maximum: Self) -> CountableClosedRange<Self> {
return minimum.advanced(by: -1) ... maximum
}
}
Пример:
for i in 1<!!9 { print(i, terminator: " ") }
// 0 1 2 3 4 5 6 7 8 9
Второй оператор может быть реализован аналогичным образом, используя
CountableRange
вместо CountableClosedRange
.
Зачем мне делать расширение, а не оператора?
@NoahWilder: Все операторы - это функции. Возникает вопрос: почему метод расширения, а не бесплатная функция? Я только что посмотрел, как определяется ...
. Вы также можете определить бесплатную функцию public func <!! <T: Strideable> (minimum: T, maximum: T) -> CountableClosedRange<T> where T.Stride: SignedInteger
- я не думаю, что это имеет значение.
Я просто подумал о другом решении; что ты думаешь? Кроме того, у вас есть идеи, как сделать так, чтобы у меня действительно было место? @MartinR
@NoahWilder: Есть также правила для пробелов вокруг операторов, см., Например, stackoverflow.com/questions/31301715/…. Вот почему for i in 1 <.< 10
не компилируется.
Не хочу подталкивать @MartinR, но есть ли у вас какие-либо предложения или обходные пути, чтобы сделать что-то вроде того, что я хотел бы сделать?
@NoahWilder: Я попытался ответить на ваш (начальный) вопрос. <!!
был просто примером, демонстрирующим, как можно определить оператор. Существует множество разрешенных символов Unicode, из которых вы можете выбирать. - Определение двух операторов для этой цели (где .<
- это просто псевдоним для ..<
), на мой взгляд, сбивает с толку и, как вы заметили, имеет «неожиданное» поведение в отношении интервалов.
Спасибо @MartinR
Вы должны увеличивать индекс вместо вычитания 1