Was bedeutet "Scale" (A = B) für eine Fallklasse?

7

Bei der Erforschung von Memoization in Scala habe ich Code gefunden, den ich nicht gekriegt habe. Ich habe versucht, dieses spezielle "Ding" zu sehen, weiß aber nicht, wie ich es nennen soll; d.h. der Begriff, auf den Bezug genommen werden soll. Außerdem ist es nicht einfach, mit einem Symbol zu suchen, äh!

Ich habe den folgenden Code gesehen, um in Scala hier zu memozieren :

%Vor%

Und es ist, was die Fallklasse ausdehnt, die mich verwirrt, den extends (A => B) -Teil. Erstens, was passiert? Zweitens, warum wird es überhaupt benötigt? Und schließlich, wie nennt man diese Art von Erbschaft? d. h. Gibt es einen bestimmten Namen oder Begriff, mit dem ich mich darauf beziehen kann?

Als nächstes sehe ich, wie Memo auf diese Weise eine Fibanocci-Nummer berechnet: hier :

%Vor%

Es ist wahrscheinlich, dass ich nicht alle "Vereinfachungen" sehe, die angewendet werden. Aber ich bin nicht in der Lage, das Ende der val -Zeile, = Memo { , herauszufinden. Also, wenn dies ausführlicher getippt würde, würde ich vielleicht den "Sprung" verstehen, der gemacht wird, wie das Memo konstruiert wird.

Jede Unterstützung wird sehr geschätzt. Danke.

    
chaotic3quilibrium 23.10.2013, 17:12
quelle

5 Antworten

3

Diese Antwort ist eine Synthese der Teilantworten von 0__ und Nicolas Rinaudo.

Zusammenfassung:

Es gibt viele praktische (aber auch stark verflochtene) Annahmen, die der Scala-Compiler trifft.

  1. Scala behandelt extends (A => B) synonym mit extends Function1[A, B] ( ScalaDoc für Funktion1 [+ T1, -R] )
  2. Eine konkrete Implementierung der vererbten abstrakten Methode apply(x: A): B von Function1 muss bereitgestellt werden; %Code%
  3. Scala geht von einem implizierten def apply(x: A): B = cache.getOrElseUpdate(x, f(x)) für den Codeblock aus, der mit match beginnt.
  4. Scala übergibt den Inhalt zwischen = Memo { , der in Element 3 gestartet wurde, als Parameter an den Memo-Fallklassenkonstruktor
  5. Scala nimmt einen impliziten Typ zwischen {} in Element 3 als {} an und der Compiler verwendet den Codeblock "match" als Überschreibung für das PartialFunction[Int, BigInt] der PartialFunction-Methode und bietet dann eine zusätzliche Überschreibung für die Methode der PartialFunction %Code%.

Details:

Der erste Codeblock, der die Fallklasse Memo definiert, kann ausführlicher geschrieben werden:

%Vor%

Der zweite Codeblock, der den Wert fibanocci definiert, kann ausführlicher als solcher geschrieben werden:

%Vor%

Er musste apply() zum Wert des zweiten Codeblocks hinzufügen, um mit einem selbstreferentiellen Problem in der Zeile isDefinedAt() fertig zu werden.

Und schließlich ist eine Beispielverwendung von Fibonacci:

%Vor%     
chaotic3quilibrium 23.10.2013, 19:56
quelle
13

A => B ist die Abkürzung für Function1[A, B] , also erweitert Memo eine Funktion von A auf B , am deutlichsten durch die Methode apply(x: A): B definiert, die definiert werden muss.

Wegen der "Infix" -Notation müssen Sie Klammern um den Typ setzen, d. h. (A => B) . Du könntest auch schreiben

%Vor%

oder

%Vor%     
0__ 23.10.2013 17:19
quelle
6

Um die Antwort von 0_ zu vervollständigen, wird fibonacci über die Methode apply des Companion-Objekts Memo erstellt, das automatisch vom Compiler generiert wird, da Memo eine Case-Klasse ist.

Dies bedeutet, dass der folgende Code für Sie generiert wird:

%Vor%

Scala hat eine spezielle Behandlung für die Methode apply : Der Name muss beim Aufruf nicht eingegeben werden. Die beiden folgenden Aufrufe sind genau gleich:

%Vor%

Der case -Block ist als Mustervergleich bekannt. Unter der Haube erzeugt es eine Teilfunktion, dh eine Funktion, die für einige ihrer Eingabeparameter definiert ist, aber nicht notwendigerweise für alle von ihnen. Ich werde nicht in die Details von Teilfunktionen gehen, da es neben dem Punkt ist ( dies ist ein Memo, das ich mir zu diesem Thema geschrieben habe, wenn Sie daran interessiert sind), aber was es hier im Wesentlichen bedeutet, ist, dass der Block case tatsächlich eine Instanz von PartialFunction .

Wenn Sie diesem Link folgen, sehen Sie, dass PartialFunction sich erweitert Function1 - das ist das erwartete Argument von Memo.apply .

Also, was dieses Bit Code eigentlich bedeutet, einmal entzuckert (wenn das ein Wort ist), ist:

%Vor%

Beachten Sie, dass ich die Handhabung des Mustervergleichs erheblich vereinfacht habe, aber ich dachte, dass das Starten einer Diskussion über unapply und unapplySeq off-topic und verwirrend wäre.

    
Nicolas Rinaudo 23.10.2013 17:48
quelle
5

Ich bin der Original Autor der Memoisierung auf diese Weise. Sie können einige Beispielverwendungen in derselben Datei sehen. Es funktioniert auch sehr gut, wenn Sie auch mehrere Argumente angeben möchten, weil Scala Tupel abrollt:

%Vor%     
pathikrit 24.10.2013 01:12
quelle
2

Noch ein Wort zu diesem extends (A => B) : Das extends hier ist nicht erforderlich, aber notwendig, wenn die Instanzen von Memo in Funktionen oder Situationen höherer Ordnung verwendet werden sollen.

Ohne diese extends (A => B) ist es völlig in Ordnung, wenn Sie die Memo instance fibonacci nur in Methodenaufrufen verwenden.

%Vor%

Zum Beispiel:

%Vor%

Aber wenn Sie es in Funktionen höherer Ordnung verwenden möchten, haben Sie einen Typenkonfliktfehler.

%Vor%

Also hilft das extends hier nur, die Instanz fibonacci für andere zu identifizieren, dass es eine apply -Methode hat und somit einige Jobs erledigen kann.

    
lcn 07.12.2013 05:19
quelle

Tags und Links