函数 head

问题描述

我正在尝试创建一个接受两个参数的函数一个由三个元素组成的元组,以及一个将分配元组值中的最后两个元素的映射。所以例如我会像这样调用函数

modulename:funcName({description,a,b},#{a=>1,b=>2)).

我无法使模式匹配起作用。我的功能看起来像这样

funcName({description,#{a:=A,b:=2}.

我无法将元组中的原子映射到映射中的值。我该怎么做。

解决方法

如果我正确理解您想要什么,这在函数头本身中是不可能的,因为用作映射键的所有变量都必须事先绑定。来自the OTP 23 highlights blog post

下面有一个非法示例,表明仍然不支持使用未绑​​定的变量作为键模式表达式的一部分。在这种情况下,Key 未绑定,并且要求必须事先绑定在 key 表达式中使用的所有变量。

illegal_example(Key,#{Key := Value}) -> Value.

所以你必须这样写:

func_name({description,Key1,Key2},Map = #{}) ->
    #{Key1 := Value1,Key2 := Value2} = Map,....

这是可行的,因为在第二行,变量 Key1Key2 已经绑定,因此它们可用于匹配映射中相应键的值。

或者,使用 maps:get 来实现相同的结果:

func_name({description,Map = #{}) ->
    Value1 = maps:get(Key1,Map),Value2 = maps:get(Key2,....
,

您可以分两步完成(以保持函数头级别的模式匹配):

funcName(T = {description,A,B},Map) ->
    funcName(T,maps:get(Map,undefined),B,Map).

funcName({description,a,b},2,Map) when A =/= undefined ->
    ...

编辑

我刚刚重新阅读了您的问题,现在不明白什么不起作用。它可以一步完成,使用您的代码(和一个小的语法更正):

-module (test).

-export ([funcName/2]).

funcName({description,#{a := A,b := 2}) ->
    A;
funcName(_,_) ->
    error.

你可以测试一下:

1> test:funcName({description,#{a => "hello",b => 2}).
"hello"
2> test:funcName({description,b => 3}).
error
3> test:funcName({description,c => 2}).
error
4> test:funcName({description,#{aa => "hello",b => 2}).
error
5> test:funcName({description,bb},b => 2}).
error
6> test:funcName({description,b,c},b => 2}).
error
7>