2013-04-24 27 views
7

Tôi đang cố gắng làm lại tất cả các vấn đề về bài tập ở nhà của mình bằng cách sử dụng Erlang, và một điều khiến tôi là cách sử dụng một danh sách các hàm không có tất cả các tham số của chúng.Currying Functions Erlang

Ví dụ: Tôi đang cố gắng để sử dụng lần này, nhưng tôi không biết làm thế nào để vượt qua trong các chức năng để nó hoạt động trên accumulator

%%inside my module) 
add(X,Y) -> X + Y. 

multiply(X,Y) -> X*Y. 

Sau đó sử dụng điều này trong dòng lệnh:

lists:foldl(fun(Function,Accumulator) -> Function(Accumulator) end, 3, [add(3),multiply(5)]). 

Trả lời

9

Trong Erlang bạn phải gọi hàm đi qua tất cả các thông số nó đòi hỏi. Nhưng bạn có thể dễ dàng tránh nó bằng cách tạo ra một hàm ẩn danh chỉ lấy những tham số bạn cần và sau đó gọi hàm của bạn đúng. Nếu bạn cần một chức năng mà phải mất một tham số X và gọi chức năng add (3, X), bạn có thể tạo ra một chức năng vô danh như thế:

fun (X) -> add(3, X) end 

Đây là một ví dụ cho nhiệm vụ của bạn:

lists:foldl(fun (Function, Accumulator) -> Function(Accumulator) end, 3, 
    [fun (X) -> add(3, X) end, fun (X) -> multiply(5, X) end]). 
0
lists:foldl(
    fun(Function,Accumulator) -> Function(Accumulator) end, 
    3, 
    [ 
     fun(X) -> modname:add(3, X) end, 
     fun(X) -> modname:multiply(5, X) end 
    ] 
). 
+0

Điều này có nghĩa là không có ứng dụng chức năng một phần trong Erlang (và không có currying), phải không? Bởi vì bạn sử dụng hàm lambda, trong khi trong Haskell chúng ta có thể có một danh sách các hàm được áp dụng một phần (?): '[(+) 1, (-) 2, (*) 3]'. Hoặc là nó vẫn giống như một phần ứng dụng chức năng? – ichistmeinname

1

Một cách khá dễ dàng có thể viết một hàm ứng dụng một phần được gọi là cách tương tự để erlang: apply/3. Nó thiếu sự sang trọng bạn có trong các ngôn ngữ hỗ trợ currying.

-module(partial). 

-export([apply/4]). 

apply(Module, Name, Arity, Args) when length(Args) < Arity -> 
    Left = Arity - length(Args), 
    fun(Args1) when length(Args1) < Left -> 
      fun(Args2) -> 
       apply(Module, Name, Arity, Args2 ++ Args1 ++ Args) 
      end; 
     (Args1) when length(Args1) > Left -> 
      erlang:error(badarg); 
     (Args1) -> 
      erlang:apply(Module, Name, Args1 ++ Args) 
    end; 
apply(_, _, Arity, Args) when length(Args) > Arity -> 
    erlang:error(badarg); 
apply(Module, Name, _, Args) -> 
    erlang:apply(Module, Name, Args). 
3

Về mặt bản địa Erlang không có bất kỳ hình thức đánh giá từng phần nào bạn muốn. Bạn sẽ phải tạo ra niềm vui của riêng bạn để làm điều đó. Tuy nhiên, nếu bạn sử dụng Erlando Monad Library thì bạn có thể sử dụng đối sánh mẫu để tạo mẫu. Nó hoạt động bằng thực tế là trình biên dịch erlang cho phép bạn chơi với AST khi biên dịch mã để bạn có thể làm những thứ tuyệt vời như thế này.