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 ... else
,Option
和其他monad等容器的集体操作。
答案 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
}
}