2009-08-21 25 views
13

Tôi muốn gọi xyz với tên của hàm cần gọi.Trong Erlang, làm thế nào để bạn gọi một hàm động?

-module(sample). 
-export([xyz/1]). 

xyz(Name) -> Name(). 

p() -> "you called p". 
g() -> "you called g". 

Nhưng tôi nhận được lỗi sau:

1> c(sample.erl). 
./sample.erl:6: Warning: function p/0 is unused 
./sample.erl:7: Warning: function g/0 is unused 
{ok,sample} 
2> sample:xyz('p'). 
** exception error: bad function p 
    in function sample:xyz/1 
3> 
+2

kiến ​​thức Erlang của tôi là gần bằng không, nhưng tôi cho rằng bạn phải xuất p (và có thể g, nếu bạn muốn để sử dụng nó). – balpha

Trả lời

22

Đúng là bạn phải xuất p và g. Sau đó bạn có thể sử dụng apply/3 để gọi nó.

erlang:apply(sample, p, []) 

Chỉ có thể sử dụng giá trị vui nhộn với cú pháp Fun (...). Bạn đang đi qua trong một giá trị nguyên tử. Một nguyên tử là một 'chức năng xấu' khi thông báo lỗi đi. Bạn có thể làm điều gì đó tương tự như

xyz(p) -> fun p/0; 
xyz(g) -> fun g/0. 

Sau đó đi trước và gọi

Fun = xyz(p), 
Fun() 
+0

Cảm ơn. Bây giờ tôi có điều này: -mô hình (mẫu). -xuất ([xyz/1, p/0, g/0]). xyz (Tên) -> áp dụng (mẫu, Tên, []). p() -> "bạn gọi là p". g() -> "bạn gọi là g". và tôi có thể làm: 26> c (sample.erl). {ok, sample} 27> mẫu: xyz ('p'). "bạn gọi là p" 28> mẫu: xyz (p). "bạn gọi là p" 29> mẫu: xyz ('g'). "bạn gọi là g" 30> mẫu: xyz (g). "bạn gọi là g" Nhưng không có cách nào để không xuất các chức năng này? Tôi không muốn người dùng mô-đun có thể nhìn thấy nó. Có vẻ như không thể làm cho nó hoạt động với áp dụng/2 hoặc. Tất nhiên, tôi là một newbie erlang – ottodidakt

+1

Bạn có thể mã hóa bản đồ cuộc gọi của bạn với sự khớp mẫu hoặc xuất các chức năng của bạn. – Zed

+0

Cách duy nhất để 'rò rỉ' một chức năng không được báo cáo là trả về một giá trị thú vị đề cập đến nó. Cũng giống như hàm xyz/1 rõ ràng của tôi trả về giá trị thú vị. – Christian

7

trận đấu Pattern là thành ngữ sử dụng:

-module(sample). 
-export([xyz/1]). 

xyz(p) -> p(); 
xyz(q) -> g(). 

p() -> "you called p". 
g() -> "you called g". 

Nếu bạn muốn trở thành động bạn có thể sử dụng một gen_event máy chủ.

Về cơ bản điều này là là một máy chủ chứa một trạng thái trong đó bao gồm cặp khóa/chức năng như vậy:

[{p, #func1}, 
{g, #func2}, 
{..., ...}, 
...] 

Bạn có thể sau đó về cơ bản ràng buộc các sự kiện để các chức năng. (Có, không cần phải nói, nhiều hơn một chút để nó hơn thế.

+1

trong khi điều này là một cách kỹ thuật để làm điều đó tôi nghĩ rằng câu hỏi là nhiều hơn hướng đến cơ học trong erlang ngôn ngữ để tự động gọi một chức năng. Hàm áp dụng là câu trả lời mà anh ta đang tìm kiếm. –

8
-module(sample). 
-export([xyz/1, p/0, g/0]). 

xyz(Name) -> ?MODULE:Name(). 

p() -> "you called p". 
g() -> "you called g". 


1> sample:xyz(p). 
"you called p" 
+1

Điều đó khá thú vị. Tôi có thể đọc về "MODULE" ở đâu? Bây giờ, nếu chúng ta chỉ có thể loại bỏ p và q. – ottodidakt

+0

Dưới đây là các macro được xác định trước: http://erlang.org/doc/reference_manual/macros.html#7.3. Thật không may Erlang chỉ có "công khai" và "tư nhân" khả năng hiển thị, nhưng không có bảo vệ và gói bảo vệ. Vì vậy, bạn hoặc xuất khẩu nó, hoặc "hardcode" các cuộc gọi. – Zed

+1

Nhưng tại sao tôi không được yêu cầu xuất trong trường hợp gọi xyz tĩnh (Name) -> p(). và được yêu cầu xuất khi nó được giới hạn động? Suy nghĩ về khả năng hiển thị "riêng tư", tôi ở trong phạm vi riêng tư, phải không? – ottodidakt

0

Một cách khác để nhìn vào nó được đó (tùy thuộc vào vấn đề bạn đang giải quyết) các cuộc gọi động đến chức năng không nhất thiết phải là Cho rằng các quá trình và thông điệp đi qua là cách bạn tổ chức mã của bạn trong Erlang vì nó là một "ngôn ngữ định hướng tương tranh", có lẽ bạn chỉ có thể sử dụng thông điệp đi qua với một lựa chọn nhận chứ không phải là bắt chước thành ngữ của một ngôn ngữ tuần tự? đối với những gì bạn muốn và nhận được trả lời tùy chỉnh dựa trên đó, đó là về kết quả của từng chức năng, chứ không phải bản thân chức năng (sau đó là tính linh hoạt và khả năng mở rộng của thông điệp, v.v.)

Alt các quy trình hough không hoàn toàn miễn phí so với việc gọi từ một mô-đun thư viện, các quy trình cấp Erlang là giá rẻ (đặc biệt nếu thông báo tin nhắn nằm trong cùng một nút). Chúng không phải là quy trình cấp hệ điều hành. Chi phí trên có thể so sánh (hoặc tốt hơn) với các lời gọi hàm động và sự khởi tạo đối tượng trong các ngôn ngữ kịch bản nặng hơn.

1

Cách dễ nhất để làm là thử xuất p và g cùng với xyz.

-export([xyz/1, p/0,g/0]). 

Sau khi xuất khẩu chức năng p và g có thể được gọi như sau:

1> sample:xyz(fun sample:p/0). 
"you called p" 
2> sample:xyz(fun sample:g/0). 
"you called g" 
Các vấn đề liên quan