在案例模式匹配中调用函数是非法模式吗?

Posted

技术标签:

【中文标题】在案例模式匹配中调用函数是非法模式吗?【英文标题】:Calling functions within case pattern matching is illegal pattern? 【发布时间】:2017-05-19 10:12:29 【问题描述】:
-module(erltoy).
-compile(export_all).

isFive(5) -> true;
isFive(_) -> false.

foo(X) ->
 case X of
  isFive(X) -> true;
  3 -> false;
  _ -> nope
end.



1> c(erltoy).
erltoy.erl:9: illegal pattern
error

我不能在模式匹配中调用函数吗?

【问题讨论】:

【参考方案1】:

isFive(X) -> true; 包含无法在编译时计算为常量的表达式,因此不是有效的pattern。如果算术表达式同时满足以下两个条件,则可以在模式中使用算术表达式:

它只使用数字或位运算符。 编译时其值可以计算为常数。

参见 Erlang 参考手册中的这个示例

case Value, Result of
    ?THRESHOLD+1, ok -> ...

【讨论】:

【参考方案2】:

要完成@byaruhaf 的回答,在编译 时,case 子句的左边部分不需要是常量。以下代码是有效的,显然,Temp 在编译时是未知的(但 foo(5) 的计算结果为 nope!)。

-module(erltoy).
-compile(export_all).

isFive(5) -> true;
isFive(_) -> false.

foo(X) ->
 Temp = isFive(X),
 case X of
  Temp -> true;
  3 -> false;
  _ -> nope
end.

左边部分甚至没有必要在执行时绑定,例如这也是有效的,有I在case评估前是未绑定的,在模式匹配时是绑定的:

get_second_element_of_3_terms_tuple_if_pos_integer(X) ->
  case X of
    _,I,_ when is_integer(I), I>0 -> true,I;
    _ -> false
  end.

案例的左边部分必须是带有可选保护序列的有效模式。

一个有效的模式是一个 erlang 术语,它可能包含未绑定的变量,如果它们遵守 2 个条件,它也可能包含算术表达式

它只使用数字或位运算符。 编译时其值可以计算为常数。

给出了保护序列的定义there in erlang documentation

最后一点,编写示例中给出的那种测试函数的常用 erlang 方法是使用不同的函数头,就像你为 isFive/1 定义所做的那样。

【讨论】:

以上是关于在案例模式匹配中调用函数是非法模式吗?的主要内容,如果未能解决你的问题,请参考以下文章

模式匹配中的非法位大小

模式匹配案例中的统一

与 Erlang 中的映射模式匹配时的非法表达式

什么是函数式语言中的“模式匹配”?

在 C++ 中有一个使用模式匹配(使用正则表达式)的函数吗?

Scala笔记--模式匹配