Scala 参数模式(Spray 路由示例)

2023-12-27

抱歉,标题含糊不清……不知道如何描述这一点。

我在 Scala 中看到/使用某种代码构造已经有一段时间了,但我不知道它是如何工作的。它看起来像这样(来自 Spray 路由的示例):

path( "foo" / Segment / Segment ) { (a,b) => {  // <-- What's this style with a,b?
...
}}

在此示例中,路径中的段分别绑定到关联块内的 a 和 b。我知道如何使用这种模式,但它是如何工作的?为什么它不将某些东西绑定到“foo”?

我对 Spray 如何实现我的目的不太感兴趣,但这是什么 Scala 设施,以及我将如何编写自己的设施?


这段代码来自一个扩展的类Directives。所以所有的方法Directives都在范围之内。

路径匹配器

没有方法/ in String, so 隐式转换 https://github.com/spray/spray/blob/master/spray-routing/src/main/scala/spray/routing/PathMatcher.scala#L122用于转换String to PathMatcher0 (PathMatcher[HNil] https://github.com/spray/spray/blob/master/spray-routing/src/main/scala/spray/routing/package.scala#L27) with method / https://github.com/spray/spray/blob/master/spray-routing/src/main/scala/spray/routing/PathMatcher.scala#L33.

Method /需要一个PathMatcher并返回一个PathMatcher.

Segment https://github.com/spray/spray/blob/master/spray-routing/src/main/scala/spray/routing/PathMatcher.scala#L336 is a PathMatcher1[String] (PathMatcher[String :: HNil]).

Method / of PathMatcher[HNil] with PathMatcher[String :: HNil]参数返回一个PathMatcher[String :: HNil].

Method / of PathMatcher[String :: HNil] with PathMatcher[String :: HNil]参数返回一个PathMatcher[String :: String :: HNil]。这是来自的黑魔法shapeless https://github.com/milessabin/shapeless。查看异构列表级联 https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/syntax/hlists.scala#L71;值得一读。

指示

所以你正在打电话method path https://github.com/spray/spray/blob/master/spray-routing/src/main/scala/spray/routing/directives/PathDirectives.scala#L31 with PathMatcher[String :: String :: HNil]作为参数。它返回一个Directive[String :: String :: HNil].

然后你正在调用方法apply on Directive with Function2[?, ?, ?] ((a, b) => ..) 作为参数。每个都有一个适当的隐式转换(参见黑魔法)Directive[A :: B :: C ...]用方法创建一个对象apply((a: A, b: B, c: C ...) => Route).

Parsing

PathMatcher包含路径解析的规则。它将结果返回为HList.

“foo”匹配器matches https://github.com/spray/spray/blob/master/spray-routing/src/main/scala/spray/routing/PathMatcher.scala#L123一个字符串并忽略它(返回HNil).

The A / B匹配器组合了 2 个匹配器(A and B) 由“/”字符串分隔。它将结果连接起来A and B using HList级联。

The Segment匹配器matches https://github.com/spray/spray/blob/master/spray-routing/src/main/scala/spray/routing/PathMatcher.scala#L338路径段并将其返回为String :: HNil.

So "foo" / Segment / Segment匹配 3 段路径,忽略第一个段并返回剩余段:String :: String :: HNil.

然后黑魔法可以让你使用Function2[String, String, Route] ((String, String) => Route)来处理String :: String :: HNil。如果没有这样的魔法,你将不得不使用这样的方法:{case a :: b :: HNil => ...}.

黑魔法

正如@AlexIv 指出的:

存在隐式转换pimpApply https://github.com/spray/spray/blob/master/spray-routing/src/main/scala/spray/routing/Directive.scala#L124对于每一个Directive[A :: B :: C ...]用方法创建一个对象apply((a: A, b: B, c: C ...) => Route).

它接受ApplyConverter隐含地。类型成员In https://github.com/spray/spray/blob/master/spray-routing/src/main/scala/spray/routing/ApplyConverter.scala#L22 of ApplyConverter代表一个适当的函数(A, B, C ...) => Route对于每一个Directive[A :: B :: C ...].

如果没有宏或样板代码,就无法创建此类隐式值。所以sbt-boilerplate https://github.com/sbt/sbt-boilerplate是用来ApplyConverter一代。看ApplyConverterInstances.scala https://github.com/spray/spray/blob/master/spray-routing/src/main/boilerplate/spray/routing/ApplyConverterInstances.scala.template.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala 参数模式(Spray 路由示例) 的相关文章

随机推荐