Как работают параметры распыления?
Я пытаюсь обдумать, как Spray реализовал свои директивы, и в частности DSL для извлечения параметров.
Я понимаю шаблон магнита (едва), но застрял на том, как ParamDefMagnet и ParamDefMagnet2 работают вместе.
def parameter(pdm: ParamDefMagnet): pdm.Out = pdm()
trait ParamDefMagnet {
type Out
def apply(): Out
}
trait ParamDefMagnet2[T] {
type Out
def apply(value: T): Out
}
type ParamDefMagnetAux[A, B] = ParamDefMagnet2[A] { type Out = B }
def ParamDefMagnetAux[A, B](f: A ⇒ B) = new ParamDefMagnet2[A] { type Out = B; def apply(value: A) = f(value) }
Я пытаюсь понять, как ParamDefManget2 неявно преобразуется в ParamDefMagnet описанным ниже неявным методом.
object ParamDefMagnet {
implicit def apply[T](value: T)(implicit pdm2: ParamDefMagnet2[T]) = new ParamDefMagnet {
type Out = pdm2.Out
def apply() = pdm2(value)
}
}
Если я позвоню parameter("name")
как "имя" неявно преобразуется в ParamDefMagnet
? И если он преобразует его в ParamDefMagnet2
сначала, тогда где value: T
приходят для того, чтобы преобразовать его в ParamDefMagnet
?
1 ответ
Итак, покопавшись в примерах, я, наконец, понял, как работает функция параметров:
def parameter(pdm: ParamDefMagnet): pdm.Out = pdm()
Пример для извлечения параметра типа String:
val p: Directive1[String] = parameter("name")
// we can then apply the function with the extracted name
p { name =>
// stuff
}
Spray использует множество неявных преобразований, но в основном, если у вас есть String
и String => Directive1[String]
Вы можете построить () => Directive1[String]
:
// Our String => Directive1[String]
val pdm2: ParamDefMagnet2[String] { type Out = Directive1[String] } = ParamDefMagnet2.fromString
// Our () => Directive1[String]
val pdm: ParamDefMagnet { type Out = Directive1[String] } = new ParamDefMagnet {
type Out = Directive1[String]
def apply() = pdm2("name")
}
val directive: Directive1[String] = pdm()
// equivalent to:
val directive2: Directive1[String] = parameter("name")
Все это то, что составляет простое parameter("name")
вызов:
val p: Directive1[String] = parameter("name")
За то, как Directive1[String]
применяется в стиле DSL, см. Как работают директивы в Spray?