Scala编程:将ifse序列转换为map流的Canonical方法

时间:2015-04-10 23:02:56

标签: scala functional-programming

Scala(或FP)中适用复杂链式if...then...语句的首选规范方法是什么?例如(元代码):

def fetchLastOrderFor(CustomerId:UUID)= {
    fetch Customer data from an Id
    if Customer exists 
       fetch extra information for that customer (address?)
       fetch latest order of that customer
       if Order exists
          fetch OrderDetails
          ....
}

到目前为止,我将其建模为嵌套match...case Some...case None的序列,返回类似Either[MotivationOfMissingOrderReturned,OrderWithAllDetails]

的内容

但是我不确定这是否是最好的方法(它看起来有点丑陋且难以阅读)或者我可以使用某种链式monad流来模拟它,如Try或{{1 }},map / filter s,也许使用优雅的Future理解。

我是FP的新手,并试图掌握如何有条不紊地将我的非功能性本能转换为FP行话。

我知道FP倾向于避免使用for来支持对if... then ... elseOption和其他monad等容器的集体操作。

2 个答案:

答案 0 :(得分:2)

一种方式是模式匹配:

def fetchLastOrderFor(CustomerId:UUID)= {
customer = fetch Customer data from an Id
customer match{
  case Some(custData) => {
    info = fetch extra information for that customer (address?)
    lastOrder = fetch latest order of that customer
    lastOrder match{
      case Some(orderData) => ...
      case None => return invalid 
    }
  }
  case None => return invalid
}

另一种是通过理解

def fetchLastOrderFor(CustomerId:UUID)= {
for{
  customer <- fetch Customer data from an Id
  info <- fetch extra information for that customer (address?)
  lastOrder <- fetch latest order of that customer
} yield { ...return some combination of the data above... }

这真的归结为一堆flatMap s

所以,这取决于你的偏好。我经常觉得模式匹配或理解对于更多的开发人员来说更具可读性,但这取决于具体情况。

但是,最终,大部分都依赖于使用正确的数据结构。 IE浏览器。以上示例最适合选项,分离或验证。

答案 1 :(得分:1)

如果你使用Option,你可以将它们全部放在一起作为理解。

def getCustomer(id: UUID): Option[Customer] = ???
def getCustomerInfo(customer: Customer): Option[CustomerInfo] = ???
def latestOrderForCustomer(customer: Customer): Option[Order]
def getOrderDetails(order: Order): Option[OrderDetails] = ???

def fetchLastOrderFor(customerId:UUID): Option[OrderDetails] = {
  for {
    customer     <- getCustomer(customerId)
    info         <- getCustomerInfo(customer)
    latestOrder  <- latestOrderForCustomer(customer)
    orderDetails <- getOrderDetails(order)
  } yield {
    orderDetails
  }
}