Erlang Thrusday – queue:out/1

今天的Erlang Thursday讲的的是queue模块原生API中的 queue:out/1 函数。

queue:out/1 是我见过的出镜率最高的队列函数或者说是队列方法。而且它在我所用到的各种语言或应用库中都存在。

“是什么让这个函数这么厉害?”,你可能会这么问我。

这应该是这个函数由元组、标签元组组成,它的不可变性,它的宽容性,以及我们最终看到它返回结果的事实,所有这些使得我希望更多的队列实现都有像这样的一个API。

首先应该由很多次我自己或别人的过往经历中,在尝试弹出队列第一个元素的时候忘了检查这个队列是否是空的,从而造成一个很不友好的运行时错误。

queue:out/1 恰恰相反,当你给它的入参是一个空队列的时候,它并不触发一个错误,而是返回一个标签元组来告诉你,你传入的队列是空的,另外它还返回一个空队列。

1
2
queue:out(queue:new()).
% {empty,{[],[]}}

如果我们的入参是一个非空队列,queue:out/1 返回一个两元素元组。第一个元素是一个标签元组,它告诉我们,我们得到了一个值以及入参队列的头部元素,第二个元素,我们得到了入参队列移除头部元素后剩下的元素组成的队列。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Queue = queue:from_list([a, b, c, d]).
% {[d],[a,b,c]}
queue:out(Queue).
% {{value,a},{[d],[b,c]}}
Queue.
% {[d],[a,b,c]}
{{value, Head}, NewQueue} = queue:out(Queue).
% {{value,a},{[d],[b,c]}}
Queue.
% {[d],[a,b,c]}
Head.
% a
NewQueue.
% {[d],[b,c]}
queue:head(NewQueue).
% b

当我们在跨语言条件下谈论队列的理论上的概念时,“pop”这个概念做了两个事情,返回队列的头部元素,同时修改队列将其头部元素删除。

由于Erlang的队列是不可改变的,那么你仔细想想几分钟,你就会感觉到 queue:out/1 这个函数的妙处了,它也做了“pop”概念中的两件事情,就是返回队列头部,同时返回一个删除了头部元素的新的队列。

Erlang的queue模块也提供了函数 queue:out_r/1 ,它的行为和 queue:out/1 基本一样,不一样的是它操作的是队列的尾部元素而不是队列的头部元素。

1
2
3
4
queue:out_r(queue:from_list([a, b, c, d])).
% {{value,d},{,[a,b]}}
queue:out_r(queue:new()).
% {empty,{[],[]}}

我希望你和我一样发现 queue:out/1 方便好用。

原文链接: https://www.proctor-it.com/erlang-thrusday-queue-out-1/