В Erlang, как вы вызываете функцию динамически? - PullRequest
13 голосов
/ 21 августа 2009

Я хочу вызвать xyz с именем вызываемой функции.

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

xyz(Name) -> Name().

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

Но я получаю следующую ошибку:

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>

Ответы [ 5 ]

23 голосов
/ 21 августа 2009

Правильно, что вы должны экспортировать p и g. Затем вы можете использовать apply / 3 для его вызова.

erlang:apply(sample, p, [])

С синтаксисом Fun (...) можно использовать только забавные значения. Вы передаете значение атома. Атом - это «плохая функция», как и сообщение об ошибке. Вы можете сделать что-то похожее на

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

Тогда иди и позвони

Fun = xyz(p),
Fun()
8 голосов
/ 21 августа 2009
-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"
7 голосов
/ 21 августа 2009

Соответствие шаблону - это идиома для использования:

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

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

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

Если вы хотите быть динамичным, вы можете использовать сервер gen_event .

По сути, это сервер, который содержит состояние, состоящее из пары ключ / функция, например:

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

Затем вы можете связать события с функциями. (Излишне говорить, что это немного больше, чем это.

1 голос
/ 26 апреля 2012

Самый простой способ сделать это - попробовать экспортировать p и g вместе с xyz.

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

После экспорта функции p и g можно вызвать следующим образом:

1> sample:xyz(fun sample:p/0).
"you called p"
2> sample:xyz(fun sample:g/0).
"you called g"
0 голосов
/ 17 сентября 2009

Другой способ взглянуть на это состоит в том, что (в зависимости от решаемой проблемы) динамические вызовы функций не обязательно являются правильным подходом. Учитывая, что процессы и передача сообщений - это способ организации кода в Erlang, поскольку это «язык, ориентированный на параллелизм», может быть, вы могли бы просто использовать передачу сообщений с избирательным приемом, а не имитировать идиомы последовательного языка? Отправьте сообщение о том, что вы хотите, и получите индивидуальный ответ на основе этого. В конце концов, речь идет о результате каждой функции, а не самой функции. (Плюс гибкость и масштабируемость передачи сообщений и т. Д.)

Хотя процессы не являются полностью бесплатными по сравнению с вызовами из библиотечного модуля, процессы уровня Erlang очень дешевы (особенно, если обмен сообщениями происходит внутри одного узла). Это не процессы уровня ОС. Затраты были бы сопоставимы (или лучше) с динамическими вызовами функций и созданием объектов в более тяжелых языках сценариев.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...