Erlang:检查重复的插入元素 [英] Erlang: check duplicate inserted elements

查看:198
本文介绍了Erlang:检查重复的插入元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道插入的元素是否重复。

I want to know if inserted elements are duplicated.

以下是我正在寻找的简单示例:

Here is simple example for what I'm looking for :

在第一次运行时应该返回false。

In first run should return false.

check_duplicate("user", "hi").

但在第二次运行中应该返回true。

But in second run should return true.

check_duplicate("user", "hi").


推荐答案

功能编程的最佳功能之一是纯功能。甚至还有Haskell等功能语言,你不能写不纯的功能。纯函数总是为相同的参数返回相同的值。不纯的功能有副作用,可以为相同的参数返回不同的结果。这意味着必须改变一些您不能看作为该函数的参数的状态。你只是要求它Erlang允许你这样做。你有很多选择如何做到这一点。最干净的是发送消息并从另一个进程接收消息。 (不管怎样,它是不纯的,但在Erlang中是惯用的,以下代码非常简单,并没有准备好用于生产,您应该使用OTP行为和设计原则。)

One of best features of functional programming is pure functions. There are even functional languages like Haskell where you can't write an impure function. A pure function always returns the same value for the same argument. An impure function has side effect and can return different result for the same argument. It means there has to change some state which you can't see as an argument to the function. You are asking just for it. Erlang allows you to do it. You have many options how to do it. The cleanest is to send a message and receive a message from another process. (It's impure anyway, but idiomatic in Erlang. The following code is very simple and not ready for production use. You should use OTP behaviours and design principles for it.)

has_dupes(Jid, Text) ->
    Ref = make_ref(),
    seen ! {Ref, self(), {Jid, Text}},
    receive {Ref, Result} -> Result end.

start_seen() ->
    spawn(fun()-> register(seen, self()), loop_seen([]) end).

loop_seen(Seen) ->
    receive {Ref, From, Term} ->
        case lists:member(Term, Seen) of
            true  ->
                From ! {Ref, true},
                loop_seen(Seen);
            false ->
                From ! {Ref, false},
                loop_seen([Term|Seen])
        end
    end.

另一个是从ets(Erlang Term Storage)存储和读取。

The other is to store and read from ets (Erlang Term Storage).

has_dupes(Jid, Text) ->
    (catch ets:new(seen, [set, named_table])),
    not ets:insert_new(seen, {{Jid, Text}}).

但是有一个catch。该表由进程所有,并在进程中断时被删除。它的名字是全球性的,等等。另一个更脏的是从进程字典中存储和读取一个值。

But there is a catch. The table is owned by the process and is deleted when the process dies. Its name is global and so on. Another one and much more dirty is to store and read a value from process dictionary.

has_dupes(Jid, Text) ->
    case get({Jid, Text}) of
        undefined ->
            put({Jid, Text}, seen),
            false;
        seen ->
            true
    end.

但这是讨厌的,你几乎永远不会使用这样的代码。在大多数情况下,您应该使用显式状态

But it is nasty and you should almost never use code like this. In most cases you should use explicit state

new_seen() -> [].

has_dupes(Jid, Text, Seen) ->
    Term = {Jid, Text},
    case lists:member(Term, Seen) of
        true  -> {true, Seen};
        false -> {false, [Term|Seen]}
    end.

它是最好的解决方案,因为它是一个纯粹的功能。您可以使用更好的数据结构,如 maps ,以获得更好的性能,当您需要观看更多的术语。

It is most time best solution because it is a pure function. You can use better data structures like sets and maps for better performance when you need to watch a bigger amount of terms.

这篇关于Erlang:检查重复的插入元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆