Scala for/yield 具有多个基于凭据的可选调用
Scala for/yield with multiple optional calls based on credentials
我需要一个完整的案例 class,与其他 3 个案例 class 一起构建,在一个电话中返回。但是,根据用户的凭据,他们可能会或可能不会访问该案例的某些部分 class。
以下是我目前的做法。(并且有效)它正在拨打电话,但之后会清除未经授权的案例 classes。如果他们没有适当的凭据和 return None,我理想情况下会停止通话(由于带宽低)。
持久实体服务调用需要一个 Option[PersonOne] 和 Option[PersonTwo],所以 .ask 必须 return 或者它说它是 returning 一个对象并且不会编译.
override def getPerson(id: UUID, credOne: Option[Boolean], credTwo: Option[Boolean]) = ServerServiceCall { _ =>
for {
g <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonGeneral)
h <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonOne) //if (credOne) **this 'if' does not work**
s <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonTwo)
} yield {
val x: Option[PersonOne] = if (credOne == Some(true)) h else None
val y: Option[PersonTwo] = if (credTwo == Some(true)) s else None
CompletePerson(g.get, x, y)
//TODO catch if no employee is returned
//throw NotFound (s"Person not Found with $id");
}
}
我不太确定你在问什么,但你是否担心如果
registry.refFor[PersonEntity](id.toString()).ask(GetPersonGeneral)
returns None
您会继续拨打昂贵的 .ask
电话吗?因为这不会发生,正如我们可以从这里看到的
def giveMeSome = {println("giving you Some"); Some(1)}
def giveMeNone = {println("giving you None"); None}
def giveMeSomeMore = {println("giving you Some more"); Some(2)}
val ans = for {
a <- giveMeSome
f <- giveMeNone
q <- giveMeSomeMore
} yield (a, f, q)
println(ans)
打印
giving you Some
giving you None
None
我们还可以看到,在这种情况下,您会得到 None
回复。我不知道你是想要 None
还是抛出错误。如果你想要一个错误,你可以把上面的包裹起来
我没有完全理解你的问题,但根据我的理解,你想先检查是否 credOne == Some(true) && credTwo == Some(true) 然后再继续 return None
override def getPerson(id: UUID, credOne: Option[Boolean], credTwo: Option[Boolean])
=
for {
cone <- credOne
ctwo <- credTwo
if cone
if ctwo
} yield {
ServerServiceCall { _ =>
for {
g <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonGeneral)
h <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonOne)
s <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonTwo)
if g.isDefined
} yield {
CompletePerson(g.get, h, s)
}
}
这是您函数的一个版本,如果适当的凭证值为 Some(true)
:
,它只会调用 ask
override def getPerson(id: UUID, credOne: Option[Boolean], credTwo: Option[Boolean]) = ServerServiceCall { _ =>
CompletePerson(
registry.refFor[PersonEntity](id.toString()).ask(GetPersonGeneral).get,
credOne.filter(_ == true).flatMap(_ => registry.refFor[PersonEntity](id.toString()).ask(GetPersonOne)),
credTwo.filter(_ == true).flatMap(_ => registry.refFor[PersonEntity](id.toString()).ask(GetPersonTwo))
)
}
关键部分是这样的:
credX.filter(_ == true).flatMap(...)
- 如果
credX
是 None
这将 return None
- 如果
credX
包含 false
它将 return None
- 如果
credX
是 Some(true)
那么 flatMap
将调用 ask
函数
- 如果
ask
returns None
那么表达式会returnNone
,否则会returnSome[PersonX]
我对某些数据类型有点不清楚,但我认为这应该让您对如何处理此代码有所了解。 (例如,裸 .get
看起来很危险,因为它可能会抛出异常)
评论后编辑
我解决了 filter(_)
的问题,它应该是 filter(_ == true)
。
看起来 ask
实际上 return 是 Option[Option[T]]
,在这种情况下,这可能更接近所需。
def getPerson(id: UUID, credOne: Option[Boolean], credTwo: Option[Boolean]) = ServerServiceCall { _ =>
for {
g <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonGeneral)
gen <- g
} yield {
val p1 = credOne.filter(_ == true).flatMap(_ => registry.refFor[PersonEntity](id.toString()).ask(GetPersonOne))).flatten
val p2 = credTwo.filter(_ == true).flatMap(_ => registry.refFor[PersonEntity](id.toString()).ask(GetPersonTwo))).flatten
CompletePerson(gen, p1, p2)
}
}
我需要一个完整的案例 class,与其他 3 个案例 class 一起构建,在一个电话中返回。但是,根据用户的凭据,他们可能会或可能不会访问该案例的某些部分 class。
以下是我目前的做法。(并且有效)它正在拨打电话,但之后会清除未经授权的案例 classes。如果他们没有适当的凭据和 return None,我理想情况下会停止通话(由于带宽低)。
持久实体服务调用需要一个 Option[PersonOne] 和 Option[PersonTwo],所以 .ask 必须 return 或者它说它是 returning 一个对象并且不会编译.
override def getPerson(id: UUID, credOne: Option[Boolean], credTwo: Option[Boolean]) = ServerServiceCall { _ =>
for {
g <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonGeneral)
h <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonOne) //if (credOne) **this 'if' does not work**
s <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonTwo)
} yield {
val x: Option[PersonOne] = if (credOne == Some(true)) h else None
val y: Option[PersonTwo] = if (credTwo == Some(true)) s else None
CompletePerson(g.get, x, y)
//TODO catch if no employee is returned
//throw NotFound (s"Person not Found with $id");
}
}
我不太确定你在问什么,但你是否担心如果
registry.refFor[PersonEntity](id.toString()).ask(GetPersonGeneral)
returns None
您会继续拨打昂贵的 .ask
电话吗?因为这不会发生,正如我们可以从这里看到的
def giveMeSome = {println("giving you Some"); Some(1)}
def giveMeNone = {println("giving you None"); None}
def giveMeSomeMore = {println("giving you Some more"); Some(2)}
val ans = for {
a <- giveMeSome
f <- giveMeNone
q <- giveMeSomeMore
} yield (a, f, q)
println(ans)
打印
giving you Some
giving you None
None
我们还可以看到,在这种情况下,您会得到 None
回复。我不知道你是想要 None
还是抛出错误。如果你想要一个错误,你可以把上面的包裹起来
我没有完全理解你的问题,但根据我的理解,你想先检查是否 credOne == Some(true) && credTwo == Some(true) 然后再继续 return None
override def getPerson(id: UUID, credOne: Option[Boolean], credTwo: Option[Boolean])
=
for {
cone <- credOne
ctwo <- credTwo
if cone
if ctwo
} yield {
ServerServiceCall { _ =>
for {
g <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonGeneral)
h <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonOne)
s <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonTwo)
if g.isDefined
} yield {
CompletePerson(g.get, h, s)
}
}
这是您函数的一个版本,如果适当的凭证值为 Some(true)
:
ask
override def getPerson(id: UUID, credOne: Option[Boolean], credTwo: Option[Boolean]) = ServerServiceCall { _ =>
CompletePerson(
registry.refFor[PersonEntity](id.toString()).ask(GetPersonGeneral).get,
credOne.filter(_ == true).flatMap(_ => registry.refFor[PersonEntity](id.toString()).ask(GetPersonOne)),
credTwo.filter(_ == true).flatMap(_ => registry.refFor[PersonEntity](id.toString()).ask(GetPersonTwo))
)
}
关键部分是这样的:
credX.filter(_ == true).flatMap(...)
- 如果
credX
是None
这将 returnNone
- 如果
credX
包含false
它将 returnNone
- 如果
credX
是Some(true)
那么flatMap
将调用ask
函数 - 如果
ask
returnsNone
那么表达式会returnNone
,否则会returnSome[PersonX]
我对某些数据类型有点不清楚,但我认为这应该让您对如何处理此代码有所了解。 (例如,裸 .get
看起来很危险,因为它可能会抛出异常)
评论后编辑
我解决了 filter(_)
的问题,它应该是 filter(_ == true)
。
看起来 ask
实际上 return 是 Option[Option[T]]
,在这种情况下,这可能更接近所需。
def getPerson(id: UUID, credOne: Option[Boolean], credTwo: Option[Boolean]) = ServerServiceCall { _ =>
for {
g <- registry.refFor[PersonEntity](id.toString()).ask(GetPersonGeneral)
gen <- g
} yield {
val p1 = credOne.filter(_ == true).flatMap(_ => registry.refFor[PersonEntity](id.toString()).ask(GetPersonOne))).flatten
val p2 = credTwo.filter(_ == true).flatMap(_ => registry.refFor[PersonEntity](id.toString()).ask(GetPersonTwo))).flatten
CompletePerson(gen, p1, p2)
}
}