Wie können Sie eine Funktion myEval(f, args)
in Scala definieren, die als Eingabe eine andere Funktion f
und Argumente args
verwendet und deren Ausgabe f(args)
?
Ich möchte nicht, dass myEval
irgendwelche Vorkenntnisse über die Arity- oder Argumenttypen von f
hat.
Warum ist das nützlich? Dies ist eine Möglichkeit, das Problem der Implementierung einer generischen Methode timeMyFunction(f, args)
zu lösen. Wenn es einen Weg gibt, dies durch irgendeine Art von Lazy Val-Konstruktion zu tun, wäre das auch interessant.
Bearbeiten : Der bessere Weg zur Implementierung einer Timing-Methode wird in diese Frage . Durch Aufrufen von timeMyFunction( { f(args) } )
wird der Funktionsaufruf in eine anonyme Funktion Unit => Unit
eingeschlossen. Also muss timeMyFunction
nur 0-arity-Funktionen übernehmen.
Edit 2 : Sehen Sie Dirks Antwort für einen vielleicht effizienteren Weg, der eine anonyme Funktion vermeidet, indem Sie f
als Referenz übergeben.
Also ist meine Rechtfertigung für die Frage jetzt nur meine Scala-Ausbildung.
Die Scala-Standardbibliothek wird Ihnen in den meisten Fällen nicht dabei helfen, Überartigkeiten zu verallgemeinern, aber Formlos ist dafür perfekt geeignet. So können Sie Ihre Funktion in Shapeless 1.2.4 schreiben:
%Vor%Und dann:
%Vor% Es sieht kompliziert aus, aber im Wesentlichen sagen Sie nur, dass Sie Beweise benötigen, dass eine Funktion f
einer beliebigen Arbitrarität in eine Funktion mit einem Argument aus einer heterogenen Liste A
in das Ergebnis R
umgewandelt werden kann. und dass das Tupel P
in eine heterogene Liste desselben Typs konvertiert werden kann.
Eine Alternative zur Verwendung von Pass-by-Name wäre:
%Vor% Obwohl dies so aussieht, als würde es someFunction
direkt aufrufen, tut es das nicht, da timeIt
das Argument "nach Namen" nimmt, dh der scala Compiler generiert eine versteckte Schließung, die den Aufruf ausführt, wenn der tatsächliche Wert wird in timeIt
selbst benötigt.
Diese Variante kann aufgrund des Overheads der "pass-by-name" -Konvention ein gewisses Timing-Rauschen verursachen.
Tags und Links scala generics lazy-evaluation