为啥 Erlang 中的模式匹配记录会抛出错误

Posted

技术标签:

【中文标题】为啥 Erlang 中的模式匹配记录会抛出错误【英文标题】:Why does pattern matching records in Erlang throw error为什么 Erlang 中的模式匹配记录会抛出错误 【发布时间】:2019-12-13 06:33:54 【问题描述】:

您好,我正在尝试使用 Erlang 中的记录语法将变量绑定到封闭记录及其字段之一,但我不断收到此错误:

d:/Erlang/AeRlang/rec.erl:19: 之前的语法错误:子

d:/Erlang/AeRlang/rec.erl:17: 函数 isMale/1 未定义

d:/Erlang/AeRlang/rec.erl:17: 警告:函数 maleChildren/1 是 未使用

-module(rec).
-export([makeFam/0]).

-record(man,name,
             age,
             children=[]).
-record(child,
    name,
    age,
    sex
).

makeFam()->
    #manname="Adrian",
         age=33,
         children=[#childname="Daniel",age=33,sex="Male",
                   #childname="Chris" ,sex="Male",
                   #childname="Anne",age=33,sex="Female"]
        .


fatherAndSons(Man#manchildren=Ch)->Man,[Elem|| Elem<-Ch,isMale(Elem)].
    
isMale(C#child_,_,Y)->
    case Y of 
        "Male"->true;
         _ ->false
    end.

我的isMale 方法有什么问题。我将封闭结构#child 绑定到变量C,并且我也在对其字段进行模式匹配。有什么问题?

P.S:这是否与在isMale 方法中我没有指定绑定变量Y 的字段的名称有关?

【问题讨论】:

【参考方案1】:

在您的child record 中获取sex 的方式存在一些错误。您可以更改您的函数fatherAndSons/1isMale/1,如下所示:

fatherAndSons(Man#manchildren=Ch)->Man,[Elem|| Elem<-Ch,isMale(Elem) == true].

isMale(C)->
    case C#child.sex of 
        "Male"->true;
         _ ->false
    end.

或者只是删除您的isMale/1 和列表理解中的模式匹配:

fatherAndSons(Man#manchildren=Ch)->
    Man, [Elem || Elem <-Ch, Elem#child.sex == "Male"].

【讨论】:

但是为什么会出现问题,因为我直接在isMale 参数上绑定变量,然后在case 子句中绑定时对其进行模式匹配。出了什么问题? case 子句中的模式匹配没有错。在记录child 中获取变量Y 的方式是错误的。只能将isMale(C#child_,_,Y)-&gt;这一行改成isMale(#childsex = Y)-&gt;【参考方案2】:

对于fatherAndSons/1isMale/1 函数,您使用错误的语法将记录匹配为函数参数。以下是一些更正的版本:

fatherAndSons(Man=#manchildren=Ch) -> Man, [Elem || Elem <- Ch, isMale(Elem)].

isMale(#childsex="Male")-> true;
isMale(_) -> false.

fatherAndSons/1 的函数头中,我们基本上是在说“Man 应该是一个#man 记录,我们将绑定到children 字段的Ch”。 = 运算符是匹配的,但您在 Man 绑定中缺少它。

对于isMale/1,我使用了两个子句,其中第一个子句匹配所有#child 记录,其sex 字段匹配字符串"Male",第二个子句匹配其他任何内容。如果您想将第二个子句限制为仅匹配 #child 记录,您可以改用:

isMale(#childsex="Male")-> true;
isMale(#child) -> false.

无论哪种方式,请注意无需将记录绑定到函数头中的变量isMale/1,因为您不需要在函数体中进行绑定。

【讨论】:

但是我没有使用=,因为这是在模式匹配整个结构时出现在Learn you a Erlang for great good 中的方式,尽管不是作为函数参数而是在方法内部。 (查看方法repairman 在您引用的repairman 函数中,Details = Rob#robot.details 行的意思是“将Details 绑定到details 字段的值Rob,这是一个实例#robot 记录。”换句话说,在这种情况下,Rob 已经绑定到 #robot 记录,这与您尝试将 Man 绑定到函数头中的 #man 记录不同。 感谢您的详尽解释!

以上是关于为啥 Erlang 中的模式匹配记录会抛出错误的主要内容,如果未能解决你的问题,请参考以下文章

为啥雪花 jdbc 会抛出 [XX000][200001] 错误

为啥 OCaml 模式匹配比 Erlang 弱?

为啥 toPandas() 会抛出错误,而 .show() 工作得很好?

为啥 `"foo".bar = 42;` 在 ES6 的严格模式下会抛出 `TypeError`?

在 Erlang 中进行模式匹配映射时,为啥这个变量是未绑定的?

为啥我的存储过程在包含在事务块中时会抛出错误?