繁体   English   中英

erl 程序输出的值与 erlang shell 输出的值不同

[英]The erl program outputs different values than what is output by the erlang shell

给定以下erlang函数

-module(fibonacci).

-export([my_function_3/1]).

my_function_3(Arg1) when Arg1==3 -> io:format("=3");
my_function_3(Arg1) when Arg1<3 -> io:format("<3");
my_function_3(Arg1) when Arg1>3 -> io:format(">3").

从命令行调用my_function_3函数显示的值与从 shell 调用时不同(见下文)。

请注意,我使用234作为参数,以便在函数的所有定义中对其进行评估。

erlang shell 调用my_function_3

$ erl
Erlang/OTP 22 [erts-10.6.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Eshell V10.6.2  (abort with ^G)
1> c(fibonacci).
{ok,fibonacci}
2> fibonacci:my_function_3(2).
<3ok
3> fibonacci:my_function_3(3).
=3ok
4> fibonacci:my_function_3(4).
>3ok

从命令行调用my_function_3

$ erlc fibonacci.erl
$ erl -noshell -s fibonacci my_function_3 2 -s init stop
>3%
$ erl -noshell -s fibonacci my_function_3 3 -s init stop
>3%
$ erl -noshell -s fibonacci my_function_3 4 -s init stop
>3%

因此,我的问题是:为什么从命令行调用函数和从erlang shell 调用函数时erlang输出不同的值?

文档

-s Mod [Func [Arg1, Arg2, ...]](init 标志)
使 init 调用指定的函数。 Func 默认启动。 如果未提供参数,则假定该函数的元数为 0。否则假定为元数 1,将列表 [Arg1,Arg2,...] 作为参数。 所有参数都作为原子传递。 请参见 init(3)。

  1. 因为这一行:

    如果未提供参数,则假定该函数的元数为 0。否则假定为元数 1,将列表 [Arg1,Arg2,...] 作为参数。

    您的函数将接收一个列表作为唯一参数。

  2. 因为这一行:

    所有参数都作为原子传递。

    列表中的所有参数都将是原子。

因此,您需要挑出列表的头部以获得唯一的参数,然后您必须将原子转换为整数才能使用==与另一个整数进行比较。 像这样:

-module(fib).
-export([my_function_3/1]).

my_function_3([Arg1|_Rest]) ->
    Arg1Int = list_to_integer(atom_to_list(Arg1)),
    print_result(Arg1Int).

print_result(Arg1) when Arg1<3 ->
    io:format("<3~n");
print_result(Arg1) when Arg1==3 ->
    io:format("=3~n");
print_result(Arg1) when Arg1>3 ->
    io:format(">3~n").

请注意,在 erlang 中,一个 term 可以与任何类型的另一个 term 进行比较,并且不会导致错误。 那是因为在 erlang 中,所有类型都有特定的顺序:

number < atom < reference < fun < port < pid < tuple < list < bit string

如您所见,列表被认为大于数字,因此作为列表的 Arg1 始终被认为大于数字 3 的原因。

使用命令行

erl -noshell -s fibonacci my_function_3 3 -s init stop

您正在调用fibonacci:my_function(['3'])而不是您期望的fibonacci:my_function(3) 请参阅 erl 的文档:

-s Mod [Func [Arg1, Arg2, ...]] (init flag)

   Makes init call the specified function. Func defaults to start. If no arguments
   are provided, the function is assumed to be of arity 0.
   Otherwise it is assumed to be of arity 1, taking the list
   [Arg1,Arg2,...] as argument. All arguments are passed as atoms. Seeinit(3).

因此,您的函数将3与一个原子['3']的列表进行比较。 在 erlang 中,总是可以在两个术语之间进行比较。 当它们具有相同的类型时; 比较像往常一样工作。 当它们具有不同的类型时,则使用类型比较,并将列表定义为大于数字:

The arguments can be of different data types. The following order is defined:

number < atom < reference < fun < port < pid < tuple < map < nil < list < bit string

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM