2015-07-12 9 views
7

Ich bin dabei, Scala durch Coursera Kurs (Progfun) zu lernen.Scala verwendet veränderbare Variablen, um seine Apis zu implementieren

Wir werden gelernt, funktional zu denken und Tail-Rekursionen zu verwenden, wenn es möglich ist, Funktionen/Methoden zu implementieren.

def foreach[T](list: List[T], f: [T] => Unit) { 
    if (!list.isEmpty) foreach(list.tail) else f(list.head) 
} 

Dann apis Ich war überrascht, als ich die folgende Implementierung in einiger Scala gefunden:

override /*IterableLike*/ 
    def foreach[B](f: A => B) { 
    var these = this 
    while (!these.isEmpty) { 
     f(these.head) 
     these = these.tail 
    } 
} 

Und als Beispiel für foreach auf einer Liste Funktion haben wir es wie zu implementieren gelehrt

Wie also werden wir gelernt, Rekursion zu verwenden und die Verwendung von veränderlichen Variablen zu vermeiden, und die API wird durch gegenteilige Techniken implementiert?

Werfen Sie einen Blick auf scala.collection.LinearSeqOptimized wo scala.collection.immutable.List erweitern. (ähnliche Implementierung in der List-Klasse selbst gefunden)

+2

Rekursion neigt dazu, einige Algorithmen einfacher und eleganter zu machen, aber langsamer zu laufen, mehr Stapel zu nehmen, wenn nicht Schwanz optimiert und erfordert einen bestimmten Denkprozess, der für einige schwierig sein kann. Viele natürliche Prozesse sind rekursiv, aber bis wir ähnliche natürliche Computer haben, die nicht helfen. Suchen Sie nach "Unterseite der Rekursion" für mehr Aussichtspunkte. Siehe http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html für Guido van Rossums Standpunkte, insbesondere die dritte. –

Antwort

4

Vergessen Sie nicht, dass Scala eine Multiparadigmensprache sein soll. Für Bildungszwecke ist es gut zu wissen, wie rekursive Tail-Call-Funktionen gelesen und geschrieben werden. Aber wenn man die Sprache Tag für Tag benutzt, ist es wichtig sich daran zu erinnern, dass es sich nicht um eine reine FP handelt.

Es ist möglich, dass ein Teil der Bibliothek TCO und die @tailrec Annotation vorausgegangen ist. Sie müssen sich die Commit-Historie ansehen, um das herauszufinden.

Diese Implementierung von foreach könnte eine veränderbare var verwenden, aber von außen scheint es rein zu sein. Letztendlich ist dies genau das, was TCO hinter den Kulissen tun würde.

4

Es gibt zwei Teile auf Ihre Frage:

So wie kommen wir Rekursion verwenden gelernt werden und zu vermeiden, mit wandelbaren Variablen

Da die Lehrer an, dass Sie entweder bereits über Imperativ wissen Programmieren mit veränderbaren Zustand und Schleifen oder wird es irgendwann während Ihrer Karriere sowieso ausgesetzt sein, so dass sie sich lieber darauf konzentrieren würden, Ihnen die Dinge beizubringen, die Sie wahrscheinlich nicht selbst aufgreifen.

Auch imperative Programmierung mit veränderlichen Zustand ist viel schwieriger zu verstehen, viel schwieriger zu verstehen und somit viel schwieriger zu lehren.

und die API wird durch gegenteilige Techniken implementiert?

Da die Scala-Standardbibliothek eine leistungsfähige Bibliothek mit hoher Leistungsfähigkeit sein soll, kein Lehrbeispiel. Vielleicht hat die Person, die diesen Code geschrieben hat, sie profiliert und gemessen, dass sie 0,001% Prozent schneller ist als die tailrekursive Version. Vielleicht, als dieser Code geschrieben wurde, konnte der Compiler die tail-rekursive Version noch nicht zuverlässig optimieren.

Vergessen Sie nicht, dass Iterable und Freunde der Eckpfeiler der Scala-Sammlungsbibliothek sind. Diese Methoden, die Sie betrachten, gehören wahrscheinlich zu den am häufigsten ausgeführten Methoden im gesamten Scala-Universum. Selbst die kleinste Leistungsoptimierung zahlt sich aus in einer Methode, die milliardenfach ausgeführt wird.