Как сопоставить шаблон в списке с одним элементом - PullRequest
2 голосов
/ 07 июля 2019

Я пытаюсь понять, как можно сопоставить шаблон в Erlang для отдельных элементов по сравнению со списками:

guarded(T) when T>5 ; T<3 -> 3+T;
guarded([X,Y]) when X>3,Y>3 ->{X+1,Y+1};
guarded([X,_|[T,_]]) when X rem 2==0, T rem 2 =/= 1-> [T,X];
guarded(_)->"something else".



guarded([1,2,3]).  -> goes into case 1 , how can i make sure it doesn't (and goes to last case)

** ошибка исключения: произошла ошибка при вычислении арифметического выражения в функции main:guarded / 1

Куда мне нужно поместить первый случай, когда я хочу сопоставить шаблон с отдельными элементами. Я имею в виду, что я хочу иметь случай, который работает для отдельных элементов и подстановочного знака-pattern тоже (последнее выражение).

Ответы [ 3 ]

5 голосов
/ 07 июля 2019

Вы можете добавить проверку is_list/1 своим охранникам, чтобы проверить, что T не список:

guarded(T) when not is_list(T) andalso (T>5 orelse T<3) -> 3+T;
guarded([X,Y]) when X>3, Y>3 ->{X+1,Y+1};
guarded([X,_|[T,_]]) when X rem 2==0, T rem 2 =/= 1-> [T,X];
guarded(_)->"something else".

Или вы можете использовать is_number/1 или is_integer/1, чтобы проверить, что T является числом или целым числом соответственно:

guarded(T) when is_number(T) andalso (T>5 orelse T<3) -> 3+T;
guarded([X,Y]) when X>3, Y>3 ->{X+1,Y+1};
guarded([X,_|[T,_]]) when X rem 2==0, T rem 2 =/= 1-> [T,X];
guarded(_)->"something else".
4 голосов
/ 07 июля 2019

В качестве альтернативы ответу Виноски вы также можете переместить менее конкретный шаблон в конец, чтобы сначала сопоставлялись списки:

guarded([X,Y]) when X>3,Y>3 ->{X+1,Y+1};
guarded([X,_|[T,_]]) when X rem 2==0, T rem 2 =/= 1-> [T,X];
guarded(T) when T>5 ; T<3 -> 3+T;
guarded(_)->"something else".

Но в этом конкретном случае это не будет работать хорошо, потому чточто-то вроде guarded([1,1]) все равно не будет соответствовать первым двум ветвям, но будет соответствовать T;это потому, что Erlang позволяет сравнивать любые два значения и просто рассматривает списки, превышающие числа.

3 голосов
/ 07 июля 2019

Я имею в виду, как реализован такой метод, как is_list (упомянутый выше)?

Используя erlang, вы можете реализовать is_list() следующим образом:

-module(my).
-compile([export_all]).

islist([]) ->     % empty list
    true;
islist([_|_]) ->  % non-empty list
    true;
islist(_) ->      % anything else
    false.

Когда вы вызываете функцию, erlang начинается с первого предложения функции в определении и пытается соответствоватьаргументы, указанные в функции, вызывают параметры в определении функции.Если совпадения нет, erlang пытается выполнить следующее предложение функции.Когда совпадение найдено, выполняется соответствующее тело функции.Если ни одно из функциональных предложений не совпадает, вы получаете ошибку function_clause.

В оболочке:

~/erlang_programs$ erl
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V6.4  (abort with ^G)

1> c(my).
{ok,my}

2> my:islist(3).
false

3> my:islist({1, 2}).
false

4> my:islist([1, 2]).
true

5> my:islist([]).
true

6> my:islist("abc"). 
true

В строке 6 вы должны знать, что "abc" является сокращениемдля списка целых чисел [97, 98, 99].В erlang строка в двойных кавычках является сокращением для списка, который содержит целочисленные кодовые точки символов в строке в двойных кавычках.

...