Как работают параметры распыления?

Я пытаюсь обдумать, как 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?

Другие вопросы по тегам