Scala 编程:将 if else 序列转换为 map 流的规范方法
Scala Programming: Canonical way to convert a sequence of if else into a flow of map
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
或 map / filter
, Future
s, 也许使用优雅的 for
理解。
我是 FP 的新手,正在尝试掌握如何有条不紊地将我的非功能性本能转化为 FP 行话。
我知道 FP 倾向于避免使用 if... then ... else
以支持对 Option
、List
和其他 monad 等容器进行集体操作。
一种方式是模式匹配:
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。上面的例子最适合 Option、Disjunction 或 Validation。
如果你使用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
}
}
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
或 map / filter
, Future
s, 也许使用优雅的 for
理解。
我是 FP 的新手,正在尝试掌握如何有条不紊地将我的非功能性本能转化为 FP 行话。
我知道 FP 倾向于避免使用 if... then ... else
以支持对 Option
、List
和其他 monad 等容器进行集体操作。
一种方式是模式匹配:
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。上面的例子最适合 Option、Disjunction 或 Validation。
如果你使用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
}
}