如何在列表和单个元素上进行模式匹配

时间:2019-07-07 10:09:41

标签: erlang pattern-matching

我试图了解如何在Erlang中对单个元素vs列表进行模式匹配:

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

当我想在单个元素上进行模式匹配时,我需要在哪里放置第一个大小写。我的意思是我也想拥有一个适用于单个元素和通配符模式(最后一个表达式)的情况。 / p>

3 个答案:

答案 0 :(得分:5)

您可以向卫兵添加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/1is_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".

答案 1 :(得分:4)

作为Vinoski答案的替代方法,您也可以将不太具体的模式移到末尾,因此列表首先匹配:

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 allows comparing any two values只考虑列表大于数字。

答案 2 :(得分:3)

  

我的意思是如何实现上述的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中,双引号字符串是包含双引号字符串中字符的整数代码点的列表的简写。