此代码来自扩展的类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
指示
所以你正在调用方法pathPathMatcher[String :: String :: HNil]作为参数。它返回一个Directive[String :: String :: HNil].
然后你用( ) 作为参数调用方法apply。每个使用方法创建对象的方法都有一个适当的隐式转换(参见黑魔法) 。DirectiveFunction2[?, ?, ?](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。