Hanno dimenticato di fare il curriculum o ho io?

7

Questa domanda è simile alla domanda pubblicata su Groovy chiama l'applicazione parziale " currying '? , ma non completamente lo stesso, e le risposte fornite non mi soddisfano davvero.

Vorrei esporre a questo punto, prima di andare oltre, che il curriculum è uno dei concetti che sono stati difficili da comprendere appieno. Penso che la ragione di ciò sia il fatto che sembrano esserci due definizioni generali di curry, e in realtà non significano la stessa cosa sia in teoria che in applicazione.

Detto questo, penso che il curry sia un concetto molto semplice una volta che si decide di prendere solo una delle due definizioni e attenersi ad essa. In effetti, il curry non dovrebbe essere difficile da capire, ma secondo la mia esperienza, capire il curry è stato l'equivalente di mostrare a un ragazzino una mela e dirgli che il frutto si chiama mela, e poi vai a chiamare quel frutto un'arancia . Il ragazzo non capirà mai il semplice concetto di una mela perché hai causato un'enorme quantità di confusione definendo la mela un'arancia.

La definizione di curring che ho accettato come quella giusta è che il curry sta assumendo una funzione di arbitraria arità e trasformandolo in più funzioni concatenabili, ognuna delle quali accetta solo un parametro (funzioni unarie). Nel codice, sarebbe simile a questo:

f(1,2,3);
//becomes
f(1)(2)(3);

Tuttavia, alcune persone, inclusi i ben noti programmatori come John Resig, spiegano che il curry è qualcosa di completamente diverso. Per loro, il curry non è altro che una semplice applicazione parziale. C'è anche una funzione javascript generalmente accettata per la scrittura:

Function.prototype.curry = function() {
    var fn = this, args = Array.prototype.slice.call(arguments);
    return function() {
      return fn.apply(this, args.concat(
        Array.prototype.slice.call(arguments)));
    };
  };

Questa funzione non fa realmente curry, ma applica parzialmente gli argomenti forniti. Il motivo per cui non penso che questa funzione sia al limite, perché si può finire con una funzione che accetta più di un argomento:

var f2 = f.curry(1); //f accepts 3 arguments f(1,2,3);
f2(2,3); // calling the resulting "curried" function.

Quindi, la mia domanda è: ho frainteso il curriculum o no?

Vi lascerò con questo post che spiega il currying in javascript, ma in un modo in cui non vedo alcun curriculum: link

    
posta Buzu 17.03.2013 - 20:58
fonte

3 risposte

7

Hai ragione nel dire che ciò che molte (se non la maggior parte) persone nella comunità JavaScript chiamano currying in realtà non corrisponde al termine definito in Haskell.

Quindi di nuovo, nemmeno l'applicazione parziale. Un'applicazione parziale di tutti gli argomenti è un'applicazione completa, ma questo non succede qui, perché se lo fai per tutti gli argomenti, non avresti ancora applicato la funzione, ma piuttosto hai creato una funzione niladica (una distinzione che non rende senso in Haskell).

Nella parte inferiore, per un programmatore JavaScript è più importante capire che cosa intendano gli altri programmatori JavaScript con "currying" o "applicazione parziale", rispetto a ciò che un programmatore non-JavaScript usa come termine.

FIY, penso che il termine corretto (e non inaudito) qui sia vincolante. Tu bind gli argomenti di una funzione. In particolare, puoi anche associare l'argomento implicito this di una funzione.

    
risposta data 17.03.2013 - 21:46
fonte
7

Penso che entrambe le cose siano strettamente correlate, e nel caso di una funzione a due argomenti fondamentalmente la stessa cosa, anche se potresti chiamare la prima cosa che hai scritto come "completa" e la seconda come "parziale", che sarebbe più precisamente chiamato una forma speciale di applicazione parziale o vincolante, considerando sempre il primo parametro.

Nel tuo esempio, f2 è f(1) nella sintassi che hai usato sopra e f2(2,3) può essere letto semplicemente come zucchero sintattico (!) per f2(2)(3) . Per me, il curriculum non è tanto la meccanica di dire alla tua lingua che vuoi dare gli argomenti uno dopo l'altro - è assolutamente utile, senza dubbio, ma solo un caso speciale di legare un argomento. L'importanza del currying, ai miei occhi, è come un costrutto teorico che ti permette di considerare solo le funzioni a un argomento, perché tutto il resto può essere comunque ridotto a questo.

    
risposta data 17.03.2013 - 21:11
fonte
5

Ritengo che la funzione curry di Jon Resig sia erroneamente definita ed è in realtà una forma di applicazione parziale.

Wikipedia ha in realtà una sezione ben scritta che combina il currying con un'applicazione parziale :

Currying and partial function application are often conflated.[10] The difference between the two is clearest for functions taking more than two arguments.

Given a function of type f:(X × Y × Z)→N, currying produces curry(f): X→(Y→(Z→N))). That is, while an evaluation of the first function might be represented as f(1, 2, 3), evaluation of the curried function would be represented as fcurried(1)(2)(3), applying each argument in turn to a single-argument function returned by the previous invocation. Note that after calling fcurried(1), we are left with a function that takes a single argument and returns another function, not a function that takes two arguments.

Ho intenzione di rompere qui perché quell'ultima riga è davvero importante. La versione di Jon Resig di curry produce una funzione che accetta due argomenti, il che significa che è non in realtà una funzione di elaborazione .

In contrast, partial function application refers to the process of fixing a number of arguments to a function, producing another function of smaller arity. Given the definition of above, we might fix (or 'bind') the first argument, producing a function of type partial(f): (Y×Z)→N. Evaluation of this function might be represented as fpartial(2,3). Note that the result of partial function application in this case is a function that takes two arguments.

Intuitively, partial function application says "if you fix the first arguments of the function, you get a function of the remaining arguments". For example, if function div stands for the division operation x/y, then div with the parameter x fixed at 1 (i.e., div 1) is another function: the same as the function inv that returns the multiplicative inverse of its argument, defined by inv(y) = 1/y.

The practical motivation for partial application is that very often the functions obtained by supplying some but not all of the arguments to a function are useful; for example, many languages have a function or operator similar to plus_one. Partial application makes it easy to define these functions, for example by creating a function that represents the addition operator with 1 bound as its first argument.

    
risposta data 18.03.2013 - 15:00
fonte

Leggi altre domande sui tag