此代码来自扩展的类Directives
。所以所有的方法Directives
都在范围内。
路径匹配器
中没有方法/
,String
所以使用隐式转换来转换String
为PathMatcher0
( PathMatcher[HNil]
) with method/
。
方法/
接受 aPathMatcher
并返回 a PathMatcher
。
Segment
是一个PathMatcher1[String]
( PathMatcher[String :: HNil]
)。
带参数/
的方法返回一个.PathMatcher[HNil]
PathMatcher[String :: HNil]
PathMatcher[String :: HNil]
带参数/
的方法返回一个. 这是来自的黑魔法。见异构列表连接;值得一读。PathMatcher[String :: HNil]
PathMatcher[String :: HNil]
PathMatcher[String :: String :: HNil]
shapeless
指示
所以你正在调用方法path
PathMatcher[String :: String :: HNil]
作为参数。它返回一个Directive[String :: String :: HNil]
.
然后你用( ) 作为参数调用方法apply
。每个使用方法创建对象的方法都有一个适当的隐式转换(参见黑魔法) 。Directive
Function2[?, ?, ?]
(a, b) => ..
Directive[A :: B :: C ...]
apply((a: A, b: B, c: C ...) => Route)
解析
PathMatcher
包含路径解析规则。它将结果作为HList
.
“foo”匹配器匹配一个字符串并忽略它(返回HNil
)。
A / B
匹配器组合了 2 个匹配器 (和A
) B
,由 "/" 字符串分隔。它连接A
并B
使用HList
连接的结果。
Segment
匹配器匹配路径段并将其作为String :: HNil
.
因此"foo" / Segment / Segment
匹配 3 个段的路径,忽略第一个段并将剩余段返回为String :: String :: HNil
.
然后黑魔法允许你使用Function2[String, String, Route]
( (String, String) => Route
) 来处理String :: String :: HNil
。如果没有这样的魔法,你将不得不使用这样的方法:{case a :: b :: HNil => ...}
.
黑魔法
正如@AlexIv 所说:
pimpApply
每个Directive[A :: B :: C ...]
使用方法创建对象的隐式转换apply((a: A, b: B, c: C ...) => Route)
。
它ApplyConverter
隐式接受。的类型In
成员ApplyConverter
代表(A, B, C ...) => Route
每个Directive[A :: B :: C ...]
.
如果没有宏或样板代码,就无法创建此类隐式值。所以sbt-boilerplate
用于ApplyConverter
生成。见ApplyConverterInstances.scala
。