Преобразовать строку в удовольствие - PullRequest
8 голосов
/ 05 января 2010

Я пытаюсь обойти проблему с файлом: consult / 1, не позволяющий кортежам с забавой в них, как в этом примере:

{add_one, fun(X) -> X+1 end}.

Чтобы обойти это, я собираюсь написать забавувнутри строки и ее оценки

{add_one, "fun(X) -> X+1 end"}.

Вопрос в том.Как превратить строку в удовольствие?

Ответы [ 5 ]

11 голосов
/ 06 января 2010
parse_fun_expr(S) ->
  {ok, Ts, _} = erl_scan:string(S),
  {ok, Exprs} = erl_parse:parse_exprs(Ts),
  {value, Fun, _} = erl_eval:exprs(Exprs, []),
  Fun.

Обратите внимание, что вам нужно точка в конце вашего забавного выражения, например, S = "fun(X) -> X + 1 end.".

6 голосов
/ 06 января 2010

file:script/1 почти делает то, что вы хотите - он вычисляет последовательность выражений erlang из файла и возвращает последний результат. Вы можете использовать его вместо file:consult/1, но вам нужно будет изменить формат файла с «term. Term. Term». давая [term, term ,term] "[термин, термин, термин]." iving [term, term, term] - поместить в файл одно выражение вместо последовательности.

2 голосов
/ 06 января 2010

Я хотел бы отметить, что ответ Зеда создает интерпретированное веселье. Когда вызывается веселье, оно входит в оценщик, который начинает оценивать абстрактное синтаксическое дерево, возвращаемое erl_parse:parse_exprs/1, которое он захватил. Глядя на созданное веселье:

11> erlang:fun_info(Fun, env).
{env,[[],none,none,
      [{clause,1,
               [{var,1,'X'}],
               [],
               [{op,1,'+',{var,1,'X'},{integer,1,1}}]}]]}
12> erlang:fun_info(Fun, module).
{module,erl_eval}

Можно видеть, что оно закрылось по синтаксически проанализированному абстрактному синтаксическому дереву, как видно из информации env, и это забавное создание внутри erlang_eval, как видно из информации module.

Возможно использовать компилятор erlang для создания скомпилированного модуля во время выполнения, и указатель на это compile: forms / 2 и code: load_binary / 3 . Но детали этого, вероятно, должны перейти к другому вопросу, связанному со стековым потоком.

0 голосов
/ 29 февраля 2012
2> F =fun(Str,Binding) ->
{ok,Ts,_} = erl_scan:string(Str),
Ts1 = case lists:reverse(Ts) of
          [{dot,_}|_] -> Ts;
          TsR -> lists:reverse([{dot,1} | TsR])
      end,
{ok,Expr} = erl_parse:parse_exprs(Ts1),
erl_eval:exprs(Expr, Binding) end.
#Fun<erl_eval.12.111823515>
3> F("A=23.",[]).
{value,23,[{'A',23}]}

5> F("12+B.",[{'B',23}]).
{value,35,[{'B',23}]}
0 голосов
/ 05 января 2010

Может быть, с помощью модуля erl_eval ?

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