简短问题:
有没有办法让scala编译器告诉我某个程序中给定点的隐式使用声明在哪里?
如果没有,是否有一个我可以手动跟踪的算法来找出自己声明隐式的位置?
长问题:
我正在关注简单的喷雾tutorial。
在下面的代码段中(来自教程的this个回购站):
pathEnd {
post {
entity(as[Question]) { question =>
completeWithLocationHeader(
resourceId = questionService.createQuestion(question),
ifDefinedStatus = 201, ifEmptyStatus = 409)
}
}
} ~
as
隐含FromRequestUnmarshaller[T]
类型(完整来源here):
def as[T](implicit um: FromRequestUnmarshaller[T]) = um
当我问IntelliJ这个隐含来自哪里时(使用CMD + SHIFT + P),我得到:
当我按照第一个hint时,我得到了这个:
trait UnmarshallerLifting {
implicit def fromRequestUnmarshaller[T](implicit um: FromMessageUnmarshaller[T]): FromRequestUnmarshaller[T] =
new FromRequestUnmarshaller[T] {
def apply(request: HttpRequest): Deserialized[T] = um(request)
}
...
这无助于我找出隐式FromRequestUnmarshaller[T]
的来源,因为如果我检查类层次结构,我无法弄清楚特征UnmarshallerLifting
如何混合到QuestionResource
中: / p>
我检查看起来可能包含此隐含的特征,例如this特征,但它不包含隐含的字符:
trait MarshallingDirectives {
import BasicDirectives._
import MiscDirectives._
import RouteDirectives._
/**
* Unmarshalls the requests entity to the given type passes it to its inner Route.
* If there is a problem with unmarshalling the request is rejected with the [[spray.routing.Rejection]]
* produced by the unmarshaller.
*/
def entity[T](um: FromRequestUnmarshaller[T]): Directive1[T] =
extract(_.request.as(um)).flatMap[T :: HNil] {
case Right(value) ⇒ provide(value)
case Left(ContentExpected) ⇒ reject(RequestEntityExpectedRejection)
case Left(UnsupportedContentType(supported)) ⇒ reject(UnsupportedRequestContentTypeRejection(supported))
case Left(MalformedContent(errorMsg, cause)) ⇒ reject(MalformedRequestContentRejection(errorMsg, cause))
} & cancelAllRejections(ofTypes(RequestEntityExpectedRejection.getClass, classOf[UnsupportedRequestContentTypeRejection]))
/**
* Returns the in-scope FromRequestUnmarshaller for the given type.
*/
def as[T](implicit um: FromRequestUnmarshaller[T]) = um
/**
* Uses the marshaller for the given type to produce a completion function that is passed to its inner route.
* You can use it do decouple marshaller resolution from request completion.
*/
def produce[T](marshaller: ToResponseMarshaller[T]): Directive[(T ⇒ Unit) :: HNil] =
extract { ctx ⇒ (value: T) ⇒ ctx.complete(value)(marshaller) } & cancelAllRejections(ofType[UnacceptedResponseContentTypeRejection])
/**
* Returns the in-scope Marshaller for the given type.
*/
def instanceOf[T](implicit m: ToResponseMarshaller[T]) = m
/**
* Completes the request using the given function. The input to the function is produced with the in-scope
* entity unmarshaller and the result value of the function is marshalled with the in-scope marshaller.
*/
def handleWith[A, B](f: A ⇒ B)(implicit um: FromRequestUnmarshaller[A], m: ToResponseMarshaller[B]): Route =
entity(um) { a ⇒ RouteDirectives.complete(f(a)) }
}
object MarshallingDirectives extends MarshallingDirectives
在看了20个不同的地方后,我感到很沮丧。
有没有办法让scala编译器告诉我在程序的给定点(在本例中为here)中使用了某个隐式(在本例中为FromRequestUnmarshaller[T]
)的位置?
如果没有,是否有一个我可以手动跟踪的算法来找出自己声明隐式的位置?
我在Google / SOF上查找了这个问题,但我发现的提示并没有帮助。我也经历了this,我仍然不知道FromRequestUnmarshaller[T]
来自哪里。
答案 0 :(得分:4)
通常我会在编译器中启用-Xlog-implicits
来查看带有隐含的内容。
此外,不推荐使用spray来支持akka-http。我建议切换。
答案 1 :(得分:4)
我这样做了(正如Michael的评论所示):
import scala.reflect.runtime.universe.reify
println(reify(entity(as[Question])))
打印出来:
Expr[spray.routing.Directive1[spray_examples.plain_rest.danielasfregola.quiz.management.entities.Question]](QuestionResource.entity(QuestionResource.as[Question](Deserializer.fromRequestUnmarshaller(Deserializer.fromMessageUnmarshaller(QuestionResource.json4sUnmarshaller(ManifestFactory.classType(classOf[spray_examples.plain_rest.danielasfregola.quiz.management.entities.Question])))))))
这直接告诉隐含来自哪里:Deserializer.fromRequestUnmarshaller
此外,通过使用InteliJ的搜索使用功能,这是另一种方式:
答案 2 :(得分:0)
Odersky建议的从his book隐式调试的方法是与scalac
一起运行-Xprint:typer
,您可以在here中详细了解。
此处复制:
object Mocha extends Application {
class PreferredDrink(val preference: String)
implicit val pref = new PreferredDrink("mocha")
def enjoy(name: String)(implicit drink: PreferredDrink) {
print("Welcome, "+ name)
print(". Enjoy a ")
print(drink.preference)
println("!")
}
enjoy("reader")
}
$ scalac -Xprint:typer mocha.scala
[[syntax trees at end of typer]]
// Scala source: mocha.scala
package <empty> {
final object Mocha extends java.lang.Object with Application
with ScalaObject {
// ...
private[this] val pref: Mocha.PreferredDrink =
new Mocha.this.PreferredDrink("mocha");
implicit <stable> <accessor>
def pref: Mocha.PreferredDrink = Mocha.this.pref;
def enjoy(name: String)
(implicit drink: Mocha.PreferredDrink): Unit = {
scala.this.Predef.print("Welcome, ".+(name));
scala.this.Predef.print(". Enjoy a ");
scala.this.Predef.print(drink.preference);
scala.this.Predef.println("!")
};
Mocha.this.enjoy("reader")(Mocha.this.pref)
}
}
再次归功于Odersky:https://www.artima.com/pins1ed/implicit-conversions-and-parameters.html#21.7