Программа erl выводит значения, отличные от того, что выводит оболочка erlang - PullRequest
2 голосов
/ 04 марта 2020

Учитывая следующую 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 из командной строки отображаются другие значения, чем при вызове ее из оболочки (см. Ниже).

Обратите внимание, что я использовал 2, 3 и 4 в качестве параметров, чтобы функция была оценена во всех ее определениях.

Вызов my_function_3 из оболочки erlang

$ 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 выводит разные значения при вызове функции из командной строки и при вызове из оболочки erlang?

Ответы [ 2 ]

2 голосов
/ 04 марта 2020

Из документов :

-s Мод [Fun c [Arg1, Arg2, ...]] (флаг инициализации)
Заставляет init вызывать указанную функцию. Fun c по умолчанию запускается. Если аргументы не предоставлены, предполагается, что функция имеет арность 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 термин можно сравнить с другим термином любого типа, и он не вызовет ошибку. Это связано с тем, что в erlang всем типам присваивается определенный порядок:

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

Как видно, список считается большим, чем число, поэтому причина в том, что ваш Arg1, который был списком, всегда был считается больше, чем число 3.

0 голосов
/ 04 марта 2020

с командной строкой

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']. В эрланге всегда возможно сравнение между двумя терминами. Когда они имеют одинаковый тип; сравнение работает как обычно. Когда они имеют другой тип, тогда используется сравнение типов, и список определяется как число больше:

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
...