In C# che fare qualcosa di simile:
class Program {
static Action Curry<T>(Action<T> action, T parameter) {
return() => action(parameter);
}
static void Foo(int i) {
Console.WriteLine("Value: {0}", i);
}
static void Main(string[] args) {
Action curried = Curry(Foo, 5);
curried();
}
}
chiaramente il metodo Foo
corrisponde al metodo Foo
, basta con le chiamate appropriate Console.WriteLine
invece di std::cout
.
Successivamente, si dichiara un metodo Curry
che accetta un Action<T>
e restituisce un Action
. In generale, un Action<T>
è un delegato che accetta un singolo parametro di tipo T
e restituisce void
. In particolare, Foo
è un Action<int>
perché accetta un parametro di tipo int
e restituisce void
. Per quanto riguarda il tipo di ritorno di Curry
, è dichiarato come Action
. Un Action
è un delegato che non ha parametri e restituisce void
.
La definizione di Curry
è piuttosto interessante. Stiamo definendo un'azione utilizzando un'espressione lambda che è una forma molto speciale di un delegato anonimo. Effettivamente
() => action(parameter)
dice che il parametro void
viene mappato action
valutato a parameter
.
Infine, nel Main
stiamo dichiarando un'istanza di Action
denominata curried
che è il risultato dell'applicazione di Curry
per Foo
con il parametro 5
. Questo ha lo stesso ruolo di bind(fun_ptr(foo), 5)
nell'esempio C++.
Infine, invochiamo il delegato appena formato curried
tramite la sintassi curried()
. Questo è come someCallback()
nell'esempio.
Il termine di fantasia per questo è currying.
Come esempio più interessante, si consideri il seguente:
class Program {
static Func<TArg, TResult> Curry<TArg, TResult>(
Func<TArg, TArg, TResult> func,
TArg arg1
) {
return arg => func(arg1, arg);
}
static int Add(int x, int y) {
return x + y;
}
static void Main(string[] args) {
Func<int, int> addFive = Curry<int, int>(Add, 5);
Console.WriteLine(addFive(7));
}
}
Qui stiamo dichiarando un metodo Curry
che accetta un delegato (Func<TArg, TArg, TResult>
che accetta due parametri dello stesso tipo TArg
e restituisce un valore di qualche altro digitare TResult
e un parametro di tipo TArg
e restituisce un delegato che accetta un singolo parametro di tipo TArg
e restituisce un valore di tipo TResult
(Func<TArg, TResult>
).
Quindi, come test, dichiariamo un metodo Add
che accetta due parametri di tipo int
e restituisce un parametro di tipo int
(a Func<int, int, int>
). Quindi in Main
viene creato un nuovo delegato denominato addFive
che funziona come un metodo che ne aggiunge cinque al parametro di input. Così
Console.WriteLine(addFive(7));
stampe 12
sulla console.
Grazie per la tua risposta dettagliata. Ho contrassegnato l'altro come risposta accettata perché è più conciso, anche se mancano alcuni dettagli importanti che il tuo ha incluso. – Catskul
Sicuro. Spero solo che il colore extra aiuti. :-) – jason
Risposta estremamente utile, questo. Introdotto un concetto brillante, curry, in un modo facile da capire. Aggiungerà sicuramente questo alla mia cassetta degli attrezzi mentale. –