[英]How can I locate where an implicit comes from in Scala?
簡短的問題:
有沒有辦法讓 Scala 編譯器告訴我在程序中給定點使用的某個隱式在哪里聲明?
如果沒有,是否有我可以手動遵循的算法來找出隱式聲明的位置?
長問題:
我正在遵循簡單的噴霧 crud 教程。
pathEnd {
post {
entity(as[Question]) { question =>
completeWithLocationHeader(
resourceId = questionService.createQuestion(question),
ifDefinedStatus = 201, ifEmptyStatus = 409)
}
}
} ~
as
需要一個FromRequestUnmarshaller[T]
類型的隱式(完整源代碼在這里):
def as[T](implicit um: FromRequestUnmarshaller[T]) = um
當我問 IntelliJ 這個隱式來自哪里(使用 CMD+SHIFT+P)時,我得到:
當我遵循第一個提示時,我得到了這個:
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
:
我檢查了看起來可能包含這種隱含的特征,例如這個特征,但它不包含隱含的:
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編譯器告訴我哪里有一定隱含的(在這個例子中FromRequestUnmarshaller[T]
在程序中給定的點使用(在本例這里)被宣布?
如果沒有,是否有我可以手動遵循的算法來找出隱式聲明的位置?
我在 Google/SOF 上尋找這個問題,但我發現的提示沒有幫助。 我也經歷過這個,但我仍然不知道FromRequestUnmarshaller[T]
來自哪里。
通常我在編譯器中啟用-Xlog-implicits
以查看-Xlog-implicits
發生了什么。
此外,spray 已被棄用,取而代之的是 akka-http。 我建議切換。
我這樣做了(正如邁克爾的評論中所建議的那樣):
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 的搜索使用功能:
Odersky 從他的書中推薦的調試隱式的方法是使用-Xprint:typer
運行scalac
,您可以在此處查看詳細信息。
復制在這里:
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)
}
}
再次歸功於奧德斯基: https ://www.artima.com/pins1ed/implicit-conversions-and-parameters.html#21.7
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.