2015-12-14 4 views
0

Извините, если это глупый вопрос, но мне интересно, есть ли способ в Swift создать тип, который исключительно содержит числа, которые строго больше нуля и где «положительность» значений применяется во время компиляции.Возможно ли создать тип «Позитивный номер» в Swift?

Например, можно создать как-то написать код

func divide(x: PositiveNumber, y: PositiveNumber){ 
    return x/y 
} 

таким образом, что

divide(1, 3) 

работает, но

divide(1, 0) 

не компилируется?

Ближе всего я мог придумать было структурой, состоящей только один ненадежного инициализаторе, что тип имеет либо положительное значение или ноль:

struct PositiveNumber { 
    let value: Float 

    init?(value: Float){ 
     if value > 0 { 
      self.value = value 
     } else { 
      return nil 
     } 
    } 
} 

func/(left: PositiveNumber, right: PositiveNumber) -> Float { 
    return left.value/right.value 
} 

func divide(x: PositiveNumber?, y: PositiveNumber?) -> Float? { 
    if let x = x, y = y { 
     return x/y 
    } 
    return nil 
} 

let x1 = PositiveNumber(value: 1) 
let y1 = PositiveNumber(value: 3) 

let x2 = PositiveNumber(value: -1) 
let y2 = PositiveNumber(value: 0) 

divide(x1, y: y1)! // .333 
divide(x2, y: y2)! // runtime error 

Это не страшно, но мы по-прежнему приходится иметь дело с много дополнительной обработки/разворачивания. Я задаю этот вопрос, потому что у меня есть много мест в моем коде, где мне нужно проверить, что значение не равно нулю, и мне любопытно, есть ли способ удалить этот код и позволить компилятору справиться с этим. Структурное решение требует почти столько же кода.

+0

возможно принять некоторые ответы или ответить на активные комментарии до тех пор, пока проблема не будет решена, ТНХ –

+0

Лучший ответ ток «это невозможно», так что я держусь в надежде, что кто-то имеет " это возможно "ответ. Если никто не появится, я закрою вопрос. – rogueleaderr

+0

Вы также понимаете, что невозможно знать любое значение, которое не является статическим до выполнения. Поэтому проверка '0' при компиляции невозможна. Тем не менее, я хотел бы видеть актуальную проблему, возможно, есть работа. –

ответ

1

Number Type build on Float

Это суть в том, содержит структуру, которая соответствует в значительной степени все поплавка соответствует тоже. Это всего лишь ванильная копия Float, измените ее по своему вкусу.


Считаете ли вы себя обычным оператором?

infix operator /+ { associativity left precedence 150 } 

func /+(lhs:Float,rhs:Float) -> Float? { 

    guard rhs > 0 else { 
     return nil 
    } 
    return lhs/rhs 
} 

let test = 2 /+ -1 // nil 
let test2 = 2 /+ 1 // 2 

let test3 = 2 /+ 1 + 2 // warning 

Это действительно не имеет значения, если вы позволите ему вернуться опциональный или значение перечисления, или различные протоколы. Вам придется обращаться с возвратом. Но таким образом вы получаете предупреждения компилятора.


Limited Номер Тип только с оператором для обработки подразделений:

Вы можете изменить математику в целом и создать тип PositiveNumber, который возвращает NaN при делении на значение меньше нуля.

public struct PositiveFloat { 
    public var value: Float 
    /// Create an instance initialized to zero. 
    public init() { 
     self.value = 0 
    } 
    /// Create an instance initialized to `value`. 
    public init(_ value: Float) { 
     self.value = value 
    } 

    public init(_ value: PositiveFloat) { 
     self.value = value.value 
    } 
} 

extension Float { 
    public var positive : PositiveFloat { 
     return PositiveFloat(self) 
    } 
} 


public func /(lhs:Float,rhs:PositiveFloat) -> Float { 
    if 0 > rhs.value { 
     return lhs/rhs.value 
    } else { 
     return Float.NaN 
    } 
} 
public func /(lhs:PositiveFloat,rhs:PositiveFloat) -> Float { 
    if 0 > rhs.value { 
     return lhs.value/rhs.value 
    } else { 
     return Float.NaN 
    } 
} 

let testNormal : Float = 10 
let testFloat : Float = -5 

let test = testFloat/testNormal.positive 
if test.isNaN { 
    // do stuff 
} 
+0

Это интересное направление. В моем конкретном случае деление на ноль - это не проблема, о которой я беспокоюсь. (Я пытался использовать его в качестве иллюстративного примера).Моя конкретная проблема заключается в том, что у меня есть унаследованная система, с которой я работаю, которая обрабатывает нуль как особый случай, поэтому код имеет тонны 'if x == 0 {error} else {doStuff}'. Я надеюсь, что я смогу найти способ использовать компилятор для обеспечения того, чтобы x не был равен нулю, поэтому я могу удалить весь этот код обработки ошибок. – rogueleaderr