【问题标题】:Erlang beginnings: moving a function from an escript into OTPErlang 开端:将函数从 escript 移动到 OTP
【发布时间】:2019-06-14 20:40:15
【问题描述】:

在“escript”in the Erlang docs 中有一个阶乘函数的简单实现。阶乘函数如下:

fac(0) -> 1;
fac(N) -> N * fac(N-1).

没关系,我可以让它工作,没问题。

不过,我想知道如何使用 rebar3 以“OTP 方式”实现同样的简单阶乘函数?

为了清楚起见,我的问题是:

  • 代码去哪了?
  • 如何从 shell 调用它?
  • 我是否也可以像通过 escript 示例一样从命令行运行它?

仅供参考,我已经开始使用rebar3。这是我所在的位置:

rebar3 new app factorial

创建一些文件,但具体而言,代码位于 src 目录中的 3 个文件中。我可以看到正在使用主管,似乎很好。

我可以通过 shell 与这个项目进行交互:

$ rebar3 shell

1> application:which_applications().
[{factorial,"An OTP application","0.1.0"},
 {inets,"INETS  CXC 138 49","7.0.3"},
 {ssl,"Erlang/OTP SSL application","9.1.1"},
 {public_key,"Public key infrastructure","1.6.4"},
 {asn1,"The Erlang ASN1 compiler version 5.0.8","5.0.8"},
 {crypto,"CRYPTO","4.4"},
 {stdlib,"ERTS  CXC 138 10","3.7"},
 {kernel,"ERTS  CXC 138 10","6.2"}]
2> application:stop(factorial).
=INFO REPORT==== 21-Jan-2019::12:42:07.484244 ===
    application: factorial
    exited: stopped
    type: temporary
ok
3> application:start(factorial).
ok

【问题讨论】:

  • 您为什么如此专注于脚本?我试过一次,但是对于我的所有程序,我都使用 erlang shell 来编译和运行我的 .erl 文件,其中包含我的 erlang 代码。无论如何,我第一次尝试钢筋是详细的here,也许它会对你有所帮助。
  • 并不是我专注于 escripts,而是因为我已经让它们工作,所以以这种方式构建问题是有意义的。来自 Python 的 escript 很有意义:获取您的参数,将它们传递给一些函数。在这一点上,我还没有摸索 OTP。

标签: erlang erlang-otp


【解决方案1】:

代码去哪了?

要“以 OTP 方式调用代码”,您可以将其放在 gen_server 后面。

对于这个简单的阶乘函数,我在src 目录中添加了一个新文件factorial.erl,它几乎是一个标准的gen_server 骨架,我的阶乘函数作为回调之一:

% factorial.erl
-module(factorial).
-behaviour(gen_server).
-export([start_link/0, stop/0, calc/1]).

<boilerplate gen_server stuff here, like init, etc.>

calc(N) ->
  {ok, Result} = gen_server:call(?SERVER, {calc, N}),
  {ok, Result}.

handle_call({calc, N}, _From, State) ->
  Factorial = factorial(N),
  Reply = {ok, Factorial},
  {reply, Reply, State};

factorial(0) ->
  1;
factorial(N) ->
  N * factorial(N-1).

由于我的rebar3 new app factorial 创建了一个主管,我修改了主管的init 以便它调用我的factorial 模块:

% factorial_sup.erl

<skeleton supervisor stuff here>

init([]) ->
  Server = {factorial, {factorial, start_link, []},
            permanent, 2000, worker, [factorial]},
  Children = [Server],
  RestartStrategy = {one_for_one, 0, 1},
  {ok, {RestartStrategy, Children}}.

如何从 shell 调用它?

$ rebar3 shell
<Enter>
1> factorial:calc(5).
{ok,120}

由于这是在主管下运行,我们仍然可以停止并重新启动它:

2> application:stop(factorial).
=INFO REPORT==== 22-Jan-2019::13:31:29.243520 ===
    application: factorial
    exited: stopped
    type: temporary
ok
3> factorial:calc(5).          
** exception exit: {noproc,{gen_server,call,[factorial,{calc,5}]}}
     in function  gen_server:call/2 (gen_server.erl, line 215)
     in call from factorial:calc/1 (/Users/robert/git/factorial/src/factorial.erl, line 32)
4> application:start(factorial).
ok
5> factorial:calc(5).           
{ok,120}

如何创建可执行文件?

正在进行中:-)

【讨论】:

  • 可执行文件呢?任何进展?我目前正在将“可执行文件”编写为 escript,但我想使用 processes/otp 来执行一些任务,所以我不确定如何将 OTP 用作 escript。如果可能的话,应该只使用传统的 OTP 应用程序并“使其可执行”吗?
  • 对不起@jacksonbenete,但从那时起我就没有在这方面工作过,所以从未结束。对不起!
猜你喜欢
  • 2020-09-12
  • 1970-01-01
  • 2011-10-17
  • 2012-10-11
  • 2011-09-01
  • 2015-12-24
  • 2012-11-29
  • 2013-11-01
  • 2017-05-30
相关资源
最近更新 更多