Play Framework [2.4.x] Twitter 示例。对发电机的这种特殊构造感到好奇
Play Framework [2.4.x] Twitter example. Curious as to this particular construct for a generator
使用此页面中的示例:
https://www.playframework.com/documentation/2.4.x/ScalaOAuth
然后我突然想到了这样的事情:
def sessionTokenPair(implicit request: RequestHeader): Option[RequestToken] = {
for {
token <- request.session.get("token")
secret <- request.session.get("secret")
} yield {
RequestToken(token, secret)
}
}
据我了解生成器(为了理解),第二个条目是基于第一个生成器的结果。
例如:secret <- request.session.get("secret")
可能来自 token <- request.session.get("token")
但很明显,当您查看结果时 RequestToken(token, secret)
情况并非如此。
How/why 这个构造是否优于简单地做:
RequestToken(request.session.get("token"), request.session.get("secret"))
啊 - 我想我可能会在问这个问题时自己回答这个问题(但它仍然没有解释两行的 "equalness?" 与通向下一行的一行......)
它的输出是 Option
,因为它来自映射过程,而如果我们直接跳转到构造函数,我们将无法处理 None
情况。
如果 secret
与 token
的生成器无关,那么谁能解释一下为什么这有效?
scala for-comprehension 是 flatMap
的语法糖。如果您使用 flatMap
代替,这就是上面的表达式:
request.session.get("token").flatMap { token =>
request.session.get("secret").flatMap { secret =>
Some(RequestToken(token, secret))
}
}
-产生 Option[RequestToken]
.
此方法的要点是仅在定义了 secret
和 token
时才生成 RequestToken
。如果 两者都未定义 ,则结果为 None
.
为了回答您的问题,for 理解中的第二个表达式仅基于第一个表达式的结果,如果第一个表达式产生 None
,则不会调用第二个表达式 - 只是就像如果得到 token
产生 None
.
则不会调用内部 flatMap
最后,我想更正您使用的一些术语。 for-comprehension 不是生成器。生成器可以与 for-comprehensions 一起使用,但那是因为它们是定义了 flatMap
和 filter
的单子。顺便说一句,任何定义了 flatMap
和 filter
的单子(例如 Option
、Future
、List
等)都可以与 for-comprehension 一起使用。
我喜欢将 <-
运算符视为 "let me take the value out of that wrapper (monad) for a second"。所以在 for comprehension 中,以下内容成立:
token = request.session.get("token") // this is an Option[Token]
token <- request.session.get("token") // this is a Token - we've taken it out of its wrapper
如果作品之一(return 和 Option
)
token <- request.session.get("token")
secret <- request.session.get("secret")
returns None
,for comprehension 的结果也将是 None
(可能不止两个产生式)。
换句话说,只有当所有这些return Some
的东西,结果才会是Some
.
的一个实例
在 Option
s 的情况下,它就像迭代具有零个或一个元素的列表的内容。
for comprehension 中第一个产生式的类型将决定整体结果的类型,在本例中为 Option
,这与方法的 return 类型匹配 sessionTokenPair
.
与简单 RequestToken(...)
的不同之处在于值被包装在 Option
中。这在 "no value" 和 "there is a value" 之间明显不同。否则你需要像 RequestToken
中的 isEmpty
方法,但这是通过使用 Option
来概括的(这是 Scala 中的首选方法)。
然后调用者可以"pattern match"结果。并且编译器将强制您以某种方式处理 Option
.
使用此页面中的示例:
https://www.playframework.com/documentation/2.4.x/ScalaOAuth
然后我突然想到了这样的事情:
def sessionTokenPair(implicit request: RequestHeader): Option[RequestToken] = {
for {
token <- request.session.get("token")
secret <- request.session.get("secret")
} yield {
RequestToken(token, secret)
}
}
据我了解生成器(为了理解),第二个条目是基于第一个生成器的结果。
例如:secret <- request.session.get("secret")
可能来自 token <- request.session.get("token")
但很明显,当您查看结果时 RequestToken(token, secret)
情况并非如此。
How/why 这个构造是否优于简单地做:
RequestToken(request.session.get("token"), request.session.get("secret"))
啊 - 我想我可能会在问这个问题时自己回答这个问题(但它仍然没有解释两行的 "equalness?" 与通向下一行的一行......)
它的输出是 Option
,因为它来自映射过程,而如果我们直接跳转到构造函数,我们将无法处理 None
情况。
如果 secret
与 token
的生成器无关,那么谁能解释一下为什么这有效?
scala for-comprehension 是 flatMap
的语法糖。如果您使用 flatMap
代替,这就是上面的表达式:
request.session.get("token").flatMap { token =>
request.session.get("secret").flatMap { secret =>
Some(RequestToken(token, secret))
}
}
-产生 Option[RequestToken]
.
此方法的要点是仅在定义了 secret
和 token
时才生成 RequestToken
。如果 两者都未定义 ,则结果为 None
.
为了回答您的问题,for 理解中的第二个表达式仅基于第一个表达式的结果,如果第一个表达式产生 None
,则不会调用第二个表达式 - 只是就像如果得到 token
产生 None
.
flatMap
最后,我想更正您使用的一些术语。 for-comprehension 不是生成器。生成器可以与 for-comprehensions 一起使用,但那是因为它们是定义了 flatMap
和 filter
的单子。顺便说一句,任何定义了 flatMap
和 filter
的单子(例如 Option
、Future
、List
等)都可以与 for-comprehension 一起使用。
我喜欢将 <-
运算符视为 "let me take the value out of that wrapper (monad) for a second"。所以在 for comprehension 中,以下内容成立:
token = request.session.get("token") // this is an Option[Token]
token <- request.session.get("token") // this is a Token - we've taken it out of its wrapper
如果作品之一(return 和 Option
)
token <- request.session.get("token")
secret <- request.session.get("secret")
returns None
,for comprehension 的结果也将是 None
(可能不止两个产生式)。
换句话说,只有当所有这些return Some
的东西,结果才会是Some
.
在 Option
s 的情况下,它就像迭代具有零个或一个元素的列表的内容。
for comprehension 中第一个产生式的类型将决定整体结果的类型,在本例中为 Option
,这与方法的 return 类型匹配 sessionTokenPair
.
与简单 RequestToken(...)
的不同之处在于值被包装在 Option
中。这在 "no value" 和 "there is a value" 之间明显不同。否则你需要像 RequestToken
中的 isEmpty
方法,但这是通过使用 Option
来概括的(这是 Scala 中的首选方法)。
然后调用者可以"pattern match"结果。并且编译器将强制您以某种方式处理 Option
.