functional scala-如何避免在可选映射上进行深度嵌套
functional scala- how to avoid deep nesting on optional mappings
我有一组按顺序完成的操作,但是如果有一个中间序列returns "null"我想提前中止操作(跳过后续步骤)。
我想出了一个这样的函数,它给定一个输入参数,对 Redis 执行多个操作,并 return 一个产品(如果存在)。由于其中一个中间请求 return 可能是空值,因此完整的操作可能 "fail" 并且我想缩短后续不必要的步骤。
这里的嵌套越来越疯狂了,我想让它更清晰。是否有适当的 "functional" 方法来执行此类 "if/else"
短路?
def getSingleProduct(firstSku: String): Option[Product] = {
val jedis = pool.getResource
val sid: Array[Byte] = jedis.get(Keys.sidForSku(firstSku, sectionId, feedId).getBytes)
Option(sid).flatMap {
sid: Array[Byte] =>
Option(jedis.get(Keys.latestVersionForSid(sectionId, feedId, sid))) flatMap {
version: Array[Byte] =>
Option(Keys.dataForSid(sectionId, feedId, version, sid)) flatMap {
getDataKey: Array[Byte] =>
Option(jedis.get(getDataKey)) flatMap {
packedData: Array[Byte] =>
val data = doSomeStuffWith(packedData)
Option(Product(data, "more interesting things"))
}
}
}
}
}
执行此操作的方法是使用 for
:
for {
sid <- Option(jedis.get(...))
version <- Option(jedis.get(..., sid, ...))
getDataKey <- Option(jedis.get(...version,...))
packedData <- Option(jedis.get(getDataKey))
} yield {
// Do stuff with packedData
}
这将 return None
如果任何 get
调用 returns None
,否则它将 return Some(x)
其中 x
是 yeild
表达式的结果。
您可能还想考虑为 jedis.get
编写一个包装器,其中 returns Option(x)
而不是使用 null
作为错误结果。
我有一组按顺序完成的操作,但是如果有一个中间序列returns "null"我想提前中止操作(跳过后续步骤)。
我想出了一个这样的函数,它给定一个输入参数,对 Redis 执行多个操作,并 return 一个产品(如果存在)。由于其中一个中间请求 return 可能是空值,因此完整的操作可能 "fail" 并且我想缩短后续不必要的步骤。
这里的嵌套越来越疯狂了,我想让它更清晰。是否有适当的 "functional" 方法来执行此类 "if/else"
短路?
def getSingleProduct(firstSku: String): Option[Product] = {
val jedis = pool.getResource
val sid: Array[Byte] = jedis.get(Keys.sidForSku(firstSku, sectionId, feedId).getBytes)
Option(sid).flatMap {
sid: Array[Byte] =>
Option(jedis.get(Keys.latestVersionForSid(sectionId, feedId, sid))) flatMap {
version: Array[Byte] =>
Option(Keys.dataForSid(sectionId, feedId, version, sid)) flatMap {
getDataKey: Array[Byte] =>
Option(jedis.get(getDataKey)) flatMap {
packedData: Array[Byte] =>
val data = doSomeStuffWith(packedData)
Option(Product(data, "more interesting things"))
}
}
}
}
}
执行此操作的方法是使用 for
:
for {
sid <- Option(jedis.get(...))
version <- Option(jedis.get(..., sid, ...))
getDataKey <- Option(jedis.get(...version,...))
packedData <- Option(jedis.get(getDataKey))
} yield {
// Do stuff with packedData
}
这将 return None
如果任何 get
调用 returns None
,否则它将 return Some(x)
其中 x
是 yeild
表达式的结果。
您可能还想考虑为 jedis.get
编写一个包装器,其中 returns Option(x)
而不是使用 null
作为错误结果。