根据this question Spray使用sbt-boilerplate生成ApplyConverter
个实例,这些实例隐式地将A :: B :: ... :: HNil => R
转换为更传统的(A, B, ...) => R
以便于使用。这个问题是在一年前提出来的;现在可以使用宏或Shapeless的新功能来完成这个,这样就不需要外部代码生成步骤吗?
答案 0 :(得分:3)
很长一段时间以来,它一直被包括在内。在无形2.0.0中,您可以执行以下操作,
scala> import shapeless._, syntax.std.function._
import shapeless._
import syntax.std.function._
scala> val f1: (Int, String, Boolean) => Int = (i, s, b) => i+s.length+(if(b) 1 else 0)
f1: (Int, String, Boolean) => Int = <function3>
scala> val pf1 = f1.toProduct
pf1: Int :: String :: Boolean :: HNil => Int = <function1>
scala> pf1(23 :: "foo" :: true :: HNil)
res0: Int = 27
scala> val pf2: (Int :: String :: HNil) => Int = l => l.head+l.tail.head.length
pf2: Int :: String :: HNil => Int = <function1>
scala> val f2 = pf2.fromProduct
f2: (Int, String) => Int = <function2>
scala> f2(23, "foo")
res1: Int = 26
(为了便于阅读,整理了REPL结果类型)。
答案 1 :(得分:0)
我认为在纯Scala中无法做到这一点,因为没有办法一般性地谈论FunctionN
接口。在宏观层面,它是可能的,但不是以使用AST表示形式的方式;执行此操作的宏可能会减少(有效地)进行字符串操作 - 在这种情况下,与sbt-boilerplate相比,它没有什么优势。
即使它确实成为可能,Spray也是一个相当基础的库,需要与其他库一起使用(因此它继续针对旧版本的Scala和Akka构建版本) - 这一点只会变得更加重要当Play被移植到Spray之上时。所以我希望在Spray引入对Shapeless 2(与Shapeless 1不兼容)的硬依赖之前会有一段时间,直到那时我想他们会尝试保持无形2喷涂路由的代码尽可能接近尽可能为shapeless1构建,以便于维护。