如何检查记录列表中是否包含Erlang中的特定记录?

2skhul33  于 2023-11-15  发布在  Erlang
关注(0)|答案(2)|浏览(230)

我是Erlang的新手,正在尝试编写一个函数,当传递一个Point记录(x,y坐标)和一个Point记录列表(x,y坐标列表)时,如果具有指定x和y坐标的Point记录是列表中的元素(即已经存在),则返回true,否则返回false。
下面是点记录的定义:

-record(point, {x, y})

字符串
这是函数的签名:

contains_point(Point, List)


我试着在Erlang文档中查找类似的问题,但没有找到我要找的东西。
我也尝试了以下代码:

contains_point(Point, List)->
    Found = fun(Point) -> lists:member(Point, List) end,
    case lists:any(Found, List) of
        true ->
            yes;
        false ->
            no
    end.


但是得到了警告消息,“变量'Point'在'fun'中隐藏”和“变量'Point'未使用”。
会很感激任何帮助,谢谢!

kcugc4gi

kcugc4gi1#

你的函数有多个问题,未使用和隐藏的变量警告暗示了这一点。

contains_point(Point, List) ->
    Found = fun(Point) -> lists:member(Point, List) end,
    case lists:any(Found, List) of
        true ->
            yes;
        false ->
            no
    end.

字符串
lists:any/2函数的第一个参数是一个 predicate 函数,该 predicate 函数将被第二个参数(列表)的每个元素调用,直到 predicate 返回true或列表耗尽。这里的 predicate 是匿名函数Found,它将返回将其列表元素参数传递给lists:member/2的结果。但是lists:member/2函数也会遍历其列表参数,如果它的第一个参数匹配列表元素,则返回true,否则返回false,这意味着Found predicate 每次lists:any/2调用它时都会检查整个列表,这是非常低效的。
你的函数也返回yesno,但根据你的描述,它应该返回一个布尔值。
修复函数的最简单方法是返回lists:member/2的结果,因为它会遍历一个列表来寻找匹配:

contains_point(Point, List) ->
    lists:member(Point, List).


或者,如果你不想使用lists模块,你可以编写函数来遍历列表本身并检查匹配:

contains_point(_, []) -> false;
contains_point(Point, [Point|_]) -> true;
contains_point(Point, [_|Tail]) ->
    contains_point(Point, Tail).


1.第一个子句匹配空列表,因此返回false。
1.第二个子句提供了真实的情况,因为它的第一个参数和列表的头部都是相同的Point值,所以它们匹配。
1.第三个子句在Point不匹配列表的头部时进行匹配;它使用Point和列表的尾部递归调用contains_point/2
这种方法本质上就是lists:member/2所做的。

uplii1fm

uplii1fm2#

fun(Point) -> lists:member(Point, List) end

字符串
这是一个匿名函数的定义,在erlang中称为fun。当你定义任何函数时,匿名或其他,你指定参数变量,例如Point,然后当你调用函数时,erlang会把你在函数调用中指定的参数赋给函数定义中的形参变量。然后你可以在函数定义中使用形参变量来完成你想要什么都行
值得注意的是,匿名函数定义等价于:

fun(X) -> lists:member(X, List) end


换句话说,函数定义中的 parameter 变量与函数定义之外的任何其他变量都没有关系。Erlang给出了两个警告:

variable 'Point' shadowed in 'fun'"


这意味着你在这个函数参数列表中使用了相同的变量名:

contains_point(Point, List) -> ...


就像你在这个(匿名)函数参数列表中所做的那样:

fun(Point) -> lists:member(Point, List) end


但它们彼此之间并不相关。

variable 'Point' is unused."


你得到这个警告是因为这里的参数变量Point:

contains_point(Point, List)


contains_point()函数定义体中从不使用。
你可以这样做:

do_stuff(Point) ->
    X = fun() -> io:format("~w~n", [Point]) end,
    X().


在这种情况下,函数并没有定义一个“隐藏”另一个变量的参数变量,因此匿名函数定义中的Point变量与do_stuff()参数列表中的Point变量相同。

相关问题