Trong C# chúng ta làm một cái gì đó như thế này:
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();
}
}
Rõ ràng phương pháp Foo
tương ứng với phương pháp của bạn Foo
, chỉ với các cuộc gọi thích hợp để Console.WriteLine
thay vì std::cout
.
Tiếp theo, chúng tôi khai báo phương thức Curry
chấp nhận số Action<T>
và trả lại Action
. Nói chung, một số Action<T>
là đại biểu chấp nhận một thông số duy nhất của loại T
và trả lại void
. Cụ thể, Foo
là Action<int>
vì nó chấp nhận một thông số loại int
và trả về void
. Đối với loại trả về là Curry
, nó được khai báo là Action
. An Action
là đại biểu không có tham số và trả về void
.
Định nghĩa của Curry
khá thú vị. Chúng tôi đang xác định một hành động bằng cách sử dụng một biểu thức lambda mà là một hình thức rất đặc biệt của một đại biểu vô danh. Hiệu quả
() => action(parameter)
nói rằng tham số void
được ánh xạ tới action
đánh giá ở parameter
.
Cuối cùng, trong Main
chúng ta đang khai báo một thể hiện của Action
tên curried
đó là kết quả của việc áp dụng Curry
để Foo
với tham số 5
. Điều này đóng vai trò giống như bind(fun_ptr(foo), 5)
trong ví dụ C++ của bạn.
Cuối cùng, chúng tôi gọi đại biểu mới được thành lập curried
thông qua cú pháp curried()
. Điều này giống như someCallback()
trong ví dụ của bạn.
Thuật ngữ ưa thích cho điều này là currying.
Như một ví dụ thú vị hơn, hãy xem xét những điều sau đây:
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));
}
}
Ở đây chúng ta đang tuyên bố một phương pháp Curry
chấp nhận một đại biểu (Func<TArg, TArg, TResult>
chấp nhận hai tham số của cùng một loại TArg
và trả về một giá trị của một số khác gõ TResult
và một tham số kiểu TArg
và trả về một đại biểu chấp nhận một tham số duy nhất của loại TArg
và trả về một giá trị kiểu TResult
(Func<TArg, TResult>
).
Sau đó, như một thử nghiệm, chúng tôi khai báo một phương thức Add
chấp nhận hai tham số kiểu int
và trả về một tham số kiểu int
(một Func<int, int, int>
). Sau đó, trong Main
, chúng tôi khởi tạo đại biểu mới có tên addFive
hoạt động như một phương thức thêm năm tham số đầu vào của nó. Do đó
Console.WriteLine(addFive(7));
in 12
trên bảng điều khiển.
Cảm ơn câu trả lời chi tiết của bạn. Tôi đánh dấu câu trả lời khác là câu trả lời được chấp nhận vì câu trả lời ngắn gọn hơn, mặc dù nó thiếu một số chi tiết quan trọng mà bạn đã đưa vào. – Catskul
Chắc chắn. Tôi chỉ hy vọng màu sắc bổ sung sẽ giúp. :-) – jason
Câu trả lời vô cùng hữu ích, điều này. Giới thiệu một khái niệm tuyệt vời, currying, một cách dễ hiểu. Chắc chắn sẽ thêm điều này vào hộp công cụ tinh thần của tôi. –