How to handle list option in Scala?

Suppose I have a function getCustomersand getOrdersByCustomer.

def getCustomer (): List [Customer] = ...
def getOrdersByCustomer (cust: Customer): List [Order] = ...

Now I can easily define a function getOrdersOfAllCustomers

def getOrdersOfAllCustomers (): List [Order] =
  for (cust <- getCustomer (); order <- getOrderByCustomer (cust)) yield order

So far so good, but what if getCustomerthey getOrdersByCustomerreturn list options?

def getCustomer (): Option [List [Customer]] = ...
def getOrdersByCustomer (cust: Customer): Option [List [Order]] = ...

Now I would like to realize two different tastes getOrdersOfAllCustomers():

  • Return No, if one of the functions returns None,
  • Return No if it getCustomerreturns None and it does not matter if getOrdersByCustomerNone is returned .

How do you propose to implement it?

+4
source share
3 answers

This should do it:

def getOrdersOfAllCustomers(): Option[List[Order]] = {
  getCustomer() flatMap { customers =>
    //optOrders is a List[Option[List[Order]]]
    val optOrders = customers map { getOrderByCustomer }

    // Any result must be wrapped in an Option because we're flatMapping 
    // the return from the initial getCustomer call
    if(optOrders contains None) None
    else {
      // map the nested Option[List[Order]]] into List[List[Order]]
      // and flatten into a List[Order]
      // This then gives a List[List[Order]] which can be flattened again
      Some(optOrders.map(_.toList.flatten).flatten)
    }
  }
}

The hard part handles the case when one of the nested calls getOrderByCustomerreturns Nonebubbles that return to the outer area (which is why using empty lists is much easier)

+2
source

I think you should consider three possibilities — a populated list, an empty list, or an error — and avoid a lot of inelegant testing to figure out which one has occurred.

Therefore use Trywith List:

def getOrdersOfAllCustomers(): Try[List[Order]] = {
  Try(funtionReturningListOfOrders())
}

, Success[List[Order]]; , Failure[List[Order]].

- , - , , . , Try , Option. filter, forEach, map .. , , .

, , , . match:

getOrdersOfAllCustomers() match {
  case Success(orders) => println(s"Awww...yeah!")
  case Failure(ex) => println(s"Stupid Scala")
}

Try, , .

+2

,

def getOrdersOfAllCustomers(): Option[List[Order]] =
  for{
    cust <- getCustomer().toList.flatten; 
    order <- getOrderByCustomer(cust).toList.flatten
  } yield order
+1

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


All Articles