这段代码来自一个扩展的类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.