2013-10-14 1 views
1

Я ясно понимаю, как работают легкие магниты в Spray, но все преобразования и импликации в FieldDefMagnet просто ударяют мои мозги. Вот часть из sources:Как работает FormFieldMagnet в спрей?

def formField(fdm: FieldDefMagnet): fdm.Out = fdm() 

trait FieldDefMagnet { 
    type Out 
    def apply(): Out 
} 
object FieldDefMagnet { 
    implicit def apply[T](value: T)(implicit fdm2: FieldDefMagnet2[T]) = new FieldDefMagnet { 
    type Out = fdm2.Out 
    def apply() = fdm2(value) 
    } 
} 
trait FieldDefMagnet2[T] { 
    type Out 
    def apply(value: T): Out 
} 
object FieldDefMagnet2 { 
    implicit def apply[A, B](implicit fdma: FieldDefMagnetAux[A, B]) = new FieldDefMagnet2[A] { 
    type Out = B 
    def apply(value: A) = fdma(value) 
    } 
} 

trait FieldDefMagnetAux[A, B] extends (A ⇒ B) 

Так что, когда я называю, например, formField("name") scalac обертывания "name" в FieldDefMagnet.apply("name"), но как другие implicits выбраны и применены?

ответ

1

Да, начинается, как вы говорите, с FieldDefMagnet.apply, а затем продолжает искать невязки метода apply и так далее для всей цепочки имплицитов.

Грубо говоря, FieldDefMagnet - это 1) значение, аннотированное с 2) неявной функциональностью и 3) тип возврата из функциональности.

FieldDefMagnet2 - это просто неявная функциональность с типом для возвращаемого типа.

FieldDefMagnetAux предлагает простой синтаксис для типа Out. Она также может быть записана в виде (и, возможно, мы должны это сделать)

type FieldDefMagnetAux[A, B] = FieldDefMagnet2[A] { type Out = B } 

Эта структура в основном необходимы для руководства вывода типа таким образом, что делает компилятор SCALA Infer большинство аргументов типа.

Все «интересные» вещи происходят в FieldDefMagnetAux, где для разных типов типов ввода вычисляется соответствующая функциональность.

EDIT: Для того, чтобы увидеть его в действии рассмотреть вопрос о расширении formField("name"), который расширяется в

formField(
    FieldDefMagnet.apply[String]("name")(
     FieldDefMagnet2.apply[String, Directive1[String]](
     FieldDefMagnetAux.forString(
      Deserializer.fromRequestUnmarshaller[spray.http.HttpForm](
      Deserializer.fromMessageUnmarshaller[spray.http.HttpForm](
       Deserializer.formUnmarshaller(
       Deserializer.UrlEncodedFormDataUnmarshaller, Deserializer.MultipartFormDataUnmarshaller))), 
      FormFieldConverter.dualModeFormFieldConverter[String](
      Deserializer.liftToSourceOption[String, String](
       Deserializer.fromFunction2Converter[String, String](Predef.conforms[String])), 
      Deserializer.liftFromEntityOptionUnmarshaller[String](
       Deserializer.liftToSourceOption[spray.http.HttpEntity, String](
       Deserializer.StringUnmarshaller))))))) 
+0

Главный момент, который я не понимаю, когда делает '' FieldDefMagnet2.apply' с FieldDefMagnetAux' неявное вызывается ? Когда мы вызываем 'fdm2 (value)', это явный вызов 'def apply (value: T): Out' в' trait FieldDefMagnet2 [T] ', и scalac не должен пытаться разрешить его с помощью convertion => look for 'implicit def apply [A, B] (неявная fdma: FieldDefMagnetAux [A, B])', поэтому, когда эта строка вызывается? –

+0

Я отредактировал свой ответ, чтобы содержать полное расширение. Чтобы ответить на ваш конкретный вопрос: все эти неявные defs вызываются перед методом, требующим их экземпляра. Они не разрешаются как «неявное преобразование», а как «неявный параметр» (который является более мощной формой неявного использования). – jrudolph