Frage

Ich glaube nicht, dass ich noch grokked currying. Ich verstehe, was es tut, und wie es zu tun. Ich kann einfach nicht glauben, von einer Situation, würde ich es verwenden.

Wo Sie currying in JavaScript verwenden (oder wo die Hauptbibliotheken es)? DOM-Manipulation oder allgemeine Anwendungsentwicklung Beispiele begrüßen zu können.

Eine der Antworten Animation erwähnt. Funktionen wie slideUp, ein Element als Argumente fadeIn nehmen und sind in der Regel eine Funktion der curried Funktion höherer Ordnung mit der Default „Animationsfunktion“ built-in zurückkehrt. Warum ist das besser als nur die höher-up-Funktion mit einigen Standardwerten anwenden?

Gibt es irgendwelche Nachteile es mit?

Wie hier angefordert sind einige gute Ressourcen auf JavaScript currying:

Ich werde mehr hinzufügen, wie sie in den Kommentaren auftauchen.


So, nach den Antworten, Striegeln und teilweise Anwendung im Allgemeinen sind Convenience-Techniken.

Wenn Sie häufig „Raffinierung“ ein High-Level-Funktion sind, indem sie es mit derselben Konfiguration aufrufen, können Sie Curry (oder verwenden Sie Resig teilweise) die übergeordnete Funktion einfach, prägnant Hilfsmethoden zu erstellen.

War es hilfreich?

Lösung

@Hank Homosexuell

Als Antwort auf EmbiggensTheMind Kommentar:

Ich kann nicht von einer Instanz denken, wo currying -mit selbst-ist nützlich in JavaScript ; Es ist eine Technik für die Anrufe für jeden Aufruf mit einem Argumente Funktionsaufrufe mit mehreren Argumenten in Funktionsketten umwandelt, aber JavaScript mehrere Argumente in einem einzigen Funktionsaufruf unterstützt.

In JavaScript-und ich nehme an den meisten anderen aktuelle Sprachen (nicht Lambda-Kalkül) -e häufig mit Teil Anwendung zugeordnet ist, though. John Resig erklärt es besser , aber das Wesentliche ist, dass einige Logik das wird auf zwei oder mehr Argumente angewendet werden, und Sie wissen nur den Wert (e) für einige dieser Argumente.

Sie Teil Anwendung verwenden können / currying diese bekannten Werte zu beheben und eine Funktion zurück, die nur die Unbekannten annimmt, zu aufgerufen werden später, wenn Sie die Werte tatsächlich haben Sie weitergeben möchten. Dies bietet eine raffinierte Möglichkeit, sich zu wiederholen, wenn Sie die gleichen integrierten JavaScript-Ins immer und immer mit den gleichen Werten aber ein Aufruf hätte. Zu stehlen Johns Beispiel:

String.prototype.csv = String.prototype.split.partial(/,\s*/);
var results = "John, Resig, Boston".csv();
alert( (results[1] == "Resig") + " The text values were split properly" );

Andere Tipps

Hier ist eine interessante und praktische Verwendung in JavaScript von currying dass verwendet Verschlüsse :

function converter(toUnit, factor, offset, input) {
    offset = offset || 0;
    return [((offset + input) * factor).toFixed(2), toUnit].join(" ");
}

var milesToKm = converter.curry('km', 1.60936, undefined);
var poundsToKg = converter.curry('kg', 0.45460, undefined);
var farenheitToCelsius = converter.curry('degrees C', 0.5556, -32);

milesToKm(10);            // returns "16.09 km"
poundsToKg(2.5);          // returns "1.14 kg"
farenheitToCelsius(98);   // returns "36.67 degrees C"

Dies beruht auf einer curry Erweiterung von Function, obwohl, wie Sie es nur apply (nichts Besonderes) verwendet sehen:

Function.prototype.curry = function() {
    if (arguments.length < 1) {
        return this; //nothing to curry with - return function
    }
    var __method = this;
    var args = toArray(arguments);
    return function() {
        return __method.apply(this, args.concat([].slice.apply(null, arguments)));
    }
}

Ich fand Funktionen, die Pythons functools.partial nützlicher in JavaScript aussehen:

function partial(fn) {
  return partialWithScope.apply(this,
    Array.prototype.concat.apply([fn, this],
      Array.prototype.slice.call(arguments, 1)));
}

function partialWithScope(fn, scope) {
  var args = Array.prototype.slice.call(arguments, 2);
  return function() {
    return fn.apply(scope, Array.prototype.concat.apply(args, arguments));
  };
}

Warum würden Sie wollen, es zu benutzen? Eine gemeinsame Situation, wo Sie diese verwenden möchten, wenn Sie this in einer Funktion auf einen Wert binden möchten:

var callback = partialWithScope(Object.function, obj);

Nun, wenn Rückruf aufgerufen wird, this Punkte obj. Dies ist nützlich in Situationen Ereignis oder etwas Platz zu sparen, weil es in der Regel Code kürzer macht.

Currying ähnelt teilweise mit dem Unterschied, dass die Funktion das currying kehrt akzeptiert nur ein Argument (soweit ich verstehe, dass).

In Übereinstimmung mit Hank Homosexuell - Es ist äußerst nützlich bei bestimmten wahren funktionalen Programmiersprachen - denn es ist ein notwendiger Bestandteil ist. Zum Beispiel in Haskell können Sie einfach nicht mehrere Parameter an eine Funktion übernehmen - Sie können das nicht in rein funktionaler Programmierung. Sie nehmen ein param zu einer Zeit und Ihre Funktion aufzubauen. In JavaScript ist es einfach nicht notwendig, trotz erfundene Beispiele wie „Konverter“. Hier ist der gleiche Wandler-Code, ohne die Notwendigkeit für currying:

var converter = function(ratio, symbol, input) {
    return (input*ratio).toFixed(2) + " " + symbol;
}

var kilosToPoundsRatio = 2.2;
var litersToUKPintsRatio = 1.75;
var litersToUSPintsRatio = 1.98;
var milesToKilometersRatio = 1.62;

converter(kilosToPoundsRatio, "lbs", 4); //8.80 lbs
converter(litersToUKPintsRatio, "imperial pints", 2.4); //4.20 imperial pints
converter(litersToUSPintsRatio, "US pints", 2.4); //4.75 US pints
converter(milesToKilometersRatio, "km", 34); //55.08 km

Ich wünsche schlecht Douglas Crockford, in „JavaScript: The Good Parts“, eine Erwähnung der Geschichte gegeben hatte und die tatsächliche Verwendung anstatt seine offhanded Bemerkungen currying. Für die längste Zeit danach zu lesen, war ich boggled, bis ich Funktionale Programmierung war das Studium und erkennen, dass ist, wo es herkommt.

Nach etwas mehr denken, ich setze sich für currying in JavaScript ein gültigen Anwendungsfall ist: wenn Sie versuchen, mit Hilfe von JavaScript mit rein funktionalen Programmiertechniken zu schreiben. Es scheint wie ein seltener Anwendungsfall aber.

Hier ist ein Beispiel.

Ich bin ein paar Felder mit JQuery instrumentiert, so kann ich sehen, was die Nutzer bis zu. Der Code sieht wie folgt aus:

$('#foo').focus(trackActivity);
$('#foo').blur(trackActivity);
$('#bar').focus(trackActivity);
$('#bar').blur(trackActivity);

(Für Nicht-JQuery Benutzer, ich sage, dass jedes Mal, wenn ein paar Felder zu bekommen oder den Fokus verlieren, mag ich die trackActivity () Funktion aufgerufen werden. Ich könnte auch eine anonyme Funktion verwenden, aber ich habe duplizieren es 4 mal, so dass ich es herausgezogen und es benannt.)

Jetzt stellt sich heraus, dass eines dieser Felder unterschiedlich gehandhabt werden muss. Ich möchte in der Lage sein, einen Parameter in weitergeben einer dieser Anrufe an unsere Tracking-Infrastruktur weitergeleitet werden. Mit currying, ich kann.

Es ist keine Magie oder etwas ... nur eine angenehme Abkürzung für anonyme Funktionen.

partial(alert, "FOO!") entspricht function(){alert("FOO!");}

partial(Math.max, 0) entspricht function(x){return Math.max(0, x);}

Die Aufrufe von Teil ( MochiKit Terminologie. Ich denke, einige andere Bibliotheken geben Funktionen eine .curry Methode, die das gleiche tut Ding) zu buchen, etwas schöner und weniger laut als die anonymen Funktionen.

Wie für Bibliotheken es, gibt es immer Funktions .

Wann ist es sinnvoll, in JS? Wahrscheinlich die gleichen Zeiten ist es sinnvoll in anderen modernen Sprachen, aber das einzige Mal, kann ich mich selbst sehe mit ihm in Verbindung mit Teil-Anwendung ist.

Ich würde sagen, dass die meisten wahrscheinlich, die ganze Animation Bibliothek in JS currying verwenden. Anstatt für jeden Anruf eine Reihe von verlagerten Elemente und eine Funktion passieren zu müssen, das beschreibt, wie das Element verhalten soll, auf eine Funktion höherer Ordnung, die alle das Timing Zeug, seine Regel einfacher für den Kunden API freizugeben, als der Öffentlichkeit sicherzustellen, werden einige Funktion wie „slideUp“, „fadeIn“, die nur Elemente als Argumente annimmt, und das sind nur einige curried Funktion die Funktion höherer Ordnung mit dem Standard „Animationsfunktion“ eingebaut.

Rückkehr

JavaScript-Funktionen sind Lamda in anderer funktionaler Sprache genannt. Es kann eine neue api (Stärkerer oder complext Funktion) basierend auf anderen Entwickler einfache Eingabe zu komponieren verwendet werden. Curry ist nur eine der Techniken. Sie können es verwenden, um eine vereinfachte api erstellen eine komplexe api zu nennen. Wenn Sie die Develper sind, die das vereinfachte api verwenden (zum Beispiel verwenden Sie jQuery einfache Manipulation zu tun), brauchen Sie nicht Curry zu verwenden. Aber wenn Sie die vereinfachte api erstellen möchten, Curry ist dein Freund. Sie haben einen JavaScript-Framework schreiben (wie jQuery, Mootools) oder Bibliothek, dann können Sie seine Leistung zu schätzen wissen. Ich schrieb eine verbesserte Curry-Funktion, bei http://blog.semanticsworks.com /2011/03/enhanced-curry-method.html . Sie brauchen nicht auf die Curry-Methode currying zu tun, es ist nur currying tun helfen, aber man kann es immer tun manuell durch eine Funktion A Schreiben () {} eine andere Funktion B zurückzukehren () {}. Um es interessanter zu machen, verwenden Sie die Funktion B () eine andere Funktion C zurück ().

Ich weiß, seinen alten Thread aber ich werde zeigen müssen, wie dies in Javascript-Bibliotheken verwendet wird:

Ich werde lodash.js Bibliothek verwenden, um diese Konzepte konkret zu beschreiben.

Beispiel:

var fn = function(a,b,c){ 
return a+b+c+(this.greet || ‘'); 
}

Partielle Anwendung:

var partialFnA = _.partial(fn, 1,3);

Currying:

var curriedFn = _.curry(fn);

Bindung:

var boundFn = _.bind(fn,object,1,3 );//object= {greet: ’!'}

Nutzung:

curriedFn(1)(3)(5); // gives 9 
or 
curriedFn(1,3)(5); // gives 9 
or 
curriedFn(1)(_,3)(2); //gives 9


partialFnA(5); //gives 9

boundFn(5); //gives 9!

Unterschied:

nach currying erhalten wir eine neue Funktion ohne Parameter gebunden Pre.

nach einem teilweisen Anwendung erhalten wir eine Funktion, die mit einigen Parametern gebunden ist vorgebunden.

in der Bindung können wir einen Kontext binden, die verwendet werden, ersetzen ‚dies‘, wenn nicht standardmäßig jede Funktion gebunden werden Fenster Umfang sein.

Advise: Es gibt keine Notwendigkeit, das Rad neu zu erfinden. Partielle Anwendung / Bindung / currying ist sehr verwandt. Sie können den Unterschied oben sehen. Verwenden Sie diese Bedeutung überall und die Menschen werden erkennen, was Sie ohne Probleme zu verstehen tun und Sie müssen weniger Code verwenden.

Ich bin damit einverstanden, dass in Zeiten würden Sie die Kugel eine pseudo-Funktion ins Rollen zu bekommen, indem die immer den Wert des ersten Arguments ausgefüllt haben. Glücklicherweise stieß ich auf eine völlig neue JavaScript-Bibliothek namens jPaq (h < a href = "http://jpaq.org/" rel = "nofollow"> ttp: //jpaq.org/ ), die diese Funktionalität bereitstellt. Das Beste an der Bibliothek ist die Tatsache, dass Sie Ihre eigene Build herunterladen können, die nur den Code enthält, die Sie benötigen.

Ich schrieb ein jPaq Beispiel, das einige coole Anwendungen der Curry-Funktion zeigt. Check it out hier: Currying Up String-Funktionen

Ich wollte nur einige Ressourcen für Functional.js hinzuzufügen:

Vortrag / Konferenz erläutern einige Anwendungen http://www.youtube.com/watch?v=HAcN3JyQoyY

Aktualisiert Functional.js Bibliothek: https://github.com/loop-recur/FunctionalJS Einige nette Helfer (sorry neu hier, kein Ruf: p): / Loop-recur / PreludeJS

Ich habe diese Bibliothek wurde unter Verwendung von viel vor kurzem die Wiederholung in einer js IRC-Clients Helfern Bibliothek zu reduzieren. Es ist toll Sachen - wirklich hilft aufzuräumen und Code vereinfachen.

Darüber hinaus, wenn die Leistung ein Problem wird (aber das lib ist ziemlich leicht), es ist leicht, einfach zu umschreiben eine native Funktion.

Sie können mit nativen binden für eine schnelle, eine Zeile Lösung

function clampAngle(min, max, angle) {
    var result, delta;
    delta = max - min;
    result = (angle - min) % delta;
    if (result < 0) {
        result += delta;
    }
    return min + result;
};

var clamp0To360 = clampAngle.bind(null, 0, 360);

console.log(clamp0To360(405)) // 45

Ein weiterer Stich an es, aus mit dem Versprechen zu arbeiten.

(Disclaimer:.. JS noob, aus der Python Welt kommt Selbst dort, currying ist alles, was nicht viel verwendet, aber es praktisch, gelegentlich kommt So cribbed ich das currying Funktion - siehe Links)

Zuerst habe ich mit einem Ajax-Aufruf am Start. Ich habe einige spezifische Verarbeitung auf Erfolg zu tun, aber bei einem Fehler, ich möchte nur dem Anwender die Rückmeldung geben, dass Aufruf etwas in Folge einige Fehler . In meinem eigentlichen Code, zeige ich die Fehlerrückmeldung in einem Bootstrap-Panel, sondern bin mit Protokollierung nur hier.

Ich habe meine Live-URL geändert, damit dies nicht kann.

function ajax_batch(e){
    var url = $(e.target).data("url");

    //induce error
    url = "x" + url;

    var promise_details = $.ajax(
        url,
        {
            headers: { Accept : "application/json" },
            // accepts : "application/json",
            beforeSend: function (request) {
                if (!this.crossDomain) {
                    request.setRequestHeader("X-CSRFToken", csrf_token);
                }
        },
        dataType : "json",
        type : "POST"}
    );
    promise_details.then(notify_batch_success, fail_status_specific_to_batch);
}

Nun, hier, um den Benutzer zu sagen, dass eine Charge ausgefallen ist, muß ich, dass Informationen in der Fehlerbehandlungsroutine schreiben, weil alle es wird immer eine Antwort vom Server ist.

Ich habe immer noch nur die Info bei Codierung zur Verfügung stehenden Zeit - in meinem Fall habe ich eine Reihe von möglichen Chargen haben, aber ich weiß nicht, welche W. O. ausgefallen die Antwort des Servers über die fehlgeschlagene URL-Analyse.

function fail_status_specific_to_batch(d){
    console.log("bad batch run, dude");
    console.log("response.status:" + d.status);
}

Lassen Sie uns es tun. Konsolenausgabe ist:

Konsole:

bad batch run, dude utility.js (line 109) response.status:404

Nun wollen sie die Dinge ein wenig ändern und einen wieder verwendbaren generischen Ausfall-Handler verwenden, sondern auch eine, die ist curried zur Laufzeit sowohl mit dem bekannten-at-Code-Zeit Aufruf Kontext und der Laufzeit verfügbar Infos von Veranstaltung.

    ... rest is as before...
    var target = $(e.target).text();
    var context = {"user_msg": "bad batch run, dude.  you were calling :" + target};
    var contexted_fail_notification = curry(generic_fail, context); 

    promise_details.then(notify_batch_success, contexted_fail_notification);
}

function generic_fail(context, d){
    console.log(context);
    console.log("response.status:" + d.status);
}

function curry(fn) {
     var slice = Array.prototype.slice,
        stored_args = slice.call(arguments, 1);
     return function () {
        var new_args = slice.call(arguments),
              args = stored_args.concat(new_args);
        return fn.apply(null, args);
     };
}

Konsole:

Object { user_msg="bad batch run, dude. you were calling :Run ACL now"} utility.js (line 117) response.status:404 utility.js (line 118)

Generell gegeben, wie weit verbreitet Callback-Nutzung in JS ist, currying scheint wie ein ziemlich nützliches Werkzeug zu haben.

https://javascriptweblog.wordpress.com / 2010/04/05 / Curry-Kochen-up-schmackhafter-Funktionen / http: //www.drdobbs .com / Open-Source / currying-and-partial-Funktionen-in-javasc / 231001821? pgno = 2

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top