Gre*_*reg 7 scala spray shapeless
抱歉模糊的标题...不知道如何表征这一点.
我已经在Scala中看到/使用过某种代码构造已有一段时间但我不知道它是如何工作的.它看起来像这样(来自Spray路由的示例):
path( "foo" / Segment / Segment ) { (a,b) => {  // <-- What's this style with a,b?
...
}}
在此示例中,路径中的Segements分别绑定到关联块内的a和b.我知道如何使用这种模式,但它是如何工作的?为什么它没有绑定到"foo"?
我不太喜欢喷雾如何为我的目的而工作,但Scala的设施是什么,我怎么写自己的?
sen*_*nia 11
此代码来自扩展的类Directives.所以所有方法Directives都在范围内.
没有方法/在String,因此隐式转换被用于转换String至PathMatcher0(PathMatcher[HNil]含)的方法/.
方法/取一个PathMatcher并返回一个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"匹配器匹配 String并忽略它(返回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.
Senia的回答有助于理解Spray-routing指令以及他们如何使用HLists来完成他们的工作.但我得到的印象是你真的只对使用的Scala结构感兴趣
path( "foo" / Segment / Segment ) { (a,b) => ... }
听起来好像你将它解释为特殊的Scala语法,它以某种方式将这两个Segment实例连接到a和b.事实并非如此.
path( "foo" / Segment / Segment )
只是一个普通的调用,path只有一个参数,一个涉及两个/方法调用的表达式.没什么好看的,只是普通的方法调用.
该调用的结果是一个函数,它需要另一个函数 - 当匹配请求进入时你想要发生的事情 - 作为参数.这就是这部分:
{ (a,b) => ... }
它只是一个带有两个参数的函数.第一部分(调用path)和第二部分(当收到匹配的消息时你想要做什么)在语法上没有任何关联.它们与Scala完全分开.但是,Spray的语义连接它们:第一部分创建一个函数,当收到匹配的消息时,它将调用第二部分.