Optional fast mode chain with arbitrary operations?

Apple provides an example of a short extra chain

class Person {
  var residence: Residence?
}

class Residence {
  var numberOfRooms = 1
}

let john = Person()

if let roomCount = john.residence?.numberOfRooms {
  println("John residence has \(roomCount) room(s).")
} else {
  println("Unable to retrieve the number of rooms.")
}

Imagine that you are trying to adjust a condition using some arithmetic operations. This results in a compiler error, since the modulo operator does not support options.

if john.residence?.numberOfRooms % 2 == 0 { 
  // compiler error: Value of optional type Int? not unwrapped
  println("John has an even number of rooms")
} else {
  println("John has an odd number of rooms")
}

Of course, you can always do something like the following, but he lacks the simplicity and conciseness of the additional chain.

if let residence = john.residence {
  if residence.numberOfRooms % 2 == 0  {
    println("John has an even number of rooms")
  }else{
    println("John has an odd number of rooms")
  }
} else {
  println("John has an odd number of rooms")
}

Are there any Swift language features that can provide a better solution?

+5
source share
7 answers

I think what you are looking for is usually called monad in functional programming.

swift, , , . ( , Haskell)

Google "monad swift" https://gist.github.com/cobbal/7562875ab5bfc6f0aed6

+3

:

switch john.residence?.numberOfRooms {
case .Some(let x) where x % 2 == 0:
    println("Even number of rooms")
default:
    println("Odd number of rooms")
}
+2

, , - , omap ( ).

extension Optional{
  func omap<K:Any>(optionalBlock:(T)->(K?))->K?{
    if self{
      return optionalBlock(self!)
    }
    return nil
  }
}

, omap , .

:

if (john.residence.omap{r in r.numberOfRooms % 2 == 0}){
  println("John has an even number of rooms")
} else {
  println("John has an odd number of rooms")
}

: https://gist.github.com/Grantismo/3e1ba0412e911dfd7cfe

0

, , , , - . :

if john.residence?.numberOfRooms && (john.residence!.numberOfRooms! % 2) == 0 {
    println("John has an even number of rooms")
} else {
    println("John has an odd number of rooms")
}

- , . , .

if Bool, , , :

extension Int{
    func isEven() -> Bool { return self % 2 == 0 }
}

if (john.residence?.numberOfRooms?.isEven() == true){
    println("John has an even number of rooms")
} else {
    println("John has an odd number of rooms")
}

if (john.residence?.numberOfRooms?.isEven())

true, numberOfRooms , isEven() false. Bool?, , Bool.

0

- Guard

func testOddEven(){
    guard let number = john.residence?.numberOfRooms else {print("Doesn't even have a residence loool"); return }
    switch number % 2 == 0 {
    case true:
        print("event")
        break;
    case false:
        print("odd")
        break;
    }
}
0

10 , , ; . tf/, , .

Double, , , swift (?) . :

extension Double {
  func divide(by: Double) -> Double {
    return (self/by)
  }
}

var optDouble: Double? = nil
var result = optDouble?.divide(by: 100.0)   // nil

optDouble = 20.25
result = optDouble?.divide(by: 100.0)       // 0.2025
0

(.. ):

if john.residence?.numberOfRooms % 2 == 0

assignment: true. MultiplicationPrecedence:

precedencegroup MultiplicationPrecedence {
  associativity:left
  higherThan: AdditionPrecedence
}

You can create your own group of predecessors with assignment: true

precedencegroup AssignmentTruePrecedence {
    assignment: true
    associativity:left
    higherThan:AdditionPrecedence
    lowerThan:MultiplicationPrecedence
}

Now you can declare your own operator, assign it to the aforementioned priority group, and define a related function to perform the operation modulo.

infix operator %| : AssignmentTruePrecedence

extension Int {

    static func %| (left: Int, right: Int)->Int {
        return left % right
    }

}

The string will work without errors with our new modulo operator:

if john.residence?.numberOfRooms %| 2 == 0

Turns out you don’t even have to declare a new statement, since re-allocating the modulo statement and assigning it to a new priority group seems to work!

infix operator % : AssignmentTruePrecedence
0
source

Source: https://habr.com/ru/post/1544977/


All Articles