2017-10-12 1 views
0

Ich habe folgenden Produkttyp Implementierung in unförmigen:Wo ist der rekursive Aufruf?

trait CsvEncoder[A] { 
    def encode(value: A): List[String] 
} 

implicit val hnilEncoder: CsvEncoder[HNil] = 
createEncoder(_ => Nil) 


implicit def hlistEncoder[H, T <: HList](
             implicit 
             hEncoder: CsvEncoder[H], 
             tEncoder: CsvEncoder[T] 
            ): CsvEncoder[H :: T] = 
createEncoder { 
    case h :: t => 
    hEncoder.encode(h) ++ tEncoder.encode(t) 
} 

und es wird wie folgt verwendet:

val reprEncoder: CsvEncoder[String :: Int :: Boolean :: HNil] = 
    implicitly 
println(reprEncoder.encode("abc" :: 123 :: true :: HNil)) 

am Beispiel Implementierung von HList Sehen, kann ich überall sieht den rekursiven Aufruf nicht. Weil HList wie eine Liste ist, sollte es rekursiv ablaufen, aber ich kann es nicht konfigurieren, wo das passiert ist.

Antwort

3

Es geschah in tEncoder.encode(t). Insbesondere wollen wir den folgenden Code analysieren:

case h :: t => 
    hEncoder.encode(h) ++ tEncoder.encode(t) 

case h :: t dekonstruiert das HList in den Kopf und Schwanzteile. Dann konvertiert den Wert h vom Typ H in eine List[String]. Danach tEncoder.encode(t) rekursiv codieren die verbleibenden HList bis es die Basis-Fall durch HNil vertreten, für die das Ergebnis ist Nil, das ist die leere List. Die Zwischenergebnisse werden verkettet unter Verwendung von ++, was der Operator ist, der zum Verketten von zwei Scala List Instanzen verwendet wird.