檢視原始碼 queue (stdlib v6.2)

FIFO 佇列的抽象資料型態。

此模組有效率地提供(雙向)FIFO 佇列。

如果引數類型錯誤,所有函式都會以 badarg 為原因失敗,例如,佇列引數不是佇列、索引不是整數,而列表引數不是列表。不正確的列表會導致內部崩潰。佇列的索引超出範圍也會導致以 badarg 為原因失敗。

某些函式(如註明)在空佇列時會以 empty 為原因失敗。

此模組使用的表示佇列的資料應被其他模組視為不透明。在抽象方面,此表示法是現有 Erlang 項的複合型別。請參閱關於資料型別的註解。任何假設瞭解格式的程式碼都處於危險的邊緣。

所有操作都具有均攤 O(1) 的執行時間,除了 all/2any/2delete/2delete_r/2delete_with/2delete_with_r/2filter/2filtermap/2fold/3join/2len/1member/2split/2,它們具有 O(n)。為了最小化佇列的大小,減少佇列操作產生的垃圾量,佇列不包含明確的長度資訊,這就是為什麼 len/1 是 O(n)。如果這個特定操作需要更好的效能,呼叫者很容易追蹤長度。

佇列是雙向的。佇列的概念圖像是一排人(項目)等待輪到他們。佇列的前端是等待時間最長的項目所在的末端。佇列的後端是項目開始等待時進入的末端。如果改用列表的概念圖像,則前端稱為頭部,後端稱為尾部。

從前端進入,從後端退出是佇列上的反向操作。

此模組有三組介面函式:「原始 API」、「擴充 API」和「Okasaki API」。

「原始 API」和「擴充 API」都使用等待項目隊列的概念圖像。兩者都有後綴 "_r" 的反向操作。

「原始 API」的項目移除函式會傳回包含已移除項目和結果佇列的複合項。「擴充 API」包含產生較少垃圾的替代函式,以及僅用於檢查佇列末端的函式。此外,「Okasaki API」函式產生的垃圾也較少。

「Okasaki API」的靈感來自 Chris Okasaki 的「純函數資料結構」。它將佇列視為列表。這個 API 被許多人認為是奇怪且可以避免的。例如,許多反向操作都有詞彙反轉的名稱,有些具有更易讀但可能較難理解的別名。

摘要

原始 API

如果 Pred(Item)Q 中的所有項目 Item 都傳回 true,則傳回 true,否則傳回 false

如果 Pred(Item)Q 中至少一個項目 Item 傳回 true,則傳回 true,否則傳回 false

傳回 Q1 的副本,其中刪除第一個與 Item 匹配的項目(如果有的話)。

傳回 Q1 的副本,其中刪除最後一個與 Item 匹配的項目(如果有的話)。

傳回 Q1 的副本,其中刪除第一個使 Pred 傳回 true 的項目(如果有的話)。

傳回 Q1 的副本,其中刪除最後一個使 Pred 傳回 true 的項目(如果有的話)。

傳回一個佇列 Q2,它是對 Q1 中的所有項目呼叫 Fun(Item) 的結果。

傳回一個佇列 Q2,它是對 Q1 中的所有項目呼叫 Fun(Item) 的結果。

Queue 的連續項目 Item 呼叫 Fun(Item, AccIn),從 AccIn == Acc0 開始。佇列會依佇列順序遍歷,即從前端到後端。Fun/2 必須傳回新的累加器,該累加器會傳遞到下一次呼叫。該函式傳回累加器的最終值。如果佇列為空,則會傳回 Acc0

傳回一個包含 L 中項目的佇列,其順序相同;列表的頭部項目成為佇列的前端項目。

Item 插入佇列 Q1 的後端。傳回結果佇列 Q2

Item 插入佇列 Q1 的前端。傳回結果佇列 Q2

測試 Q 是否為空,如果是,則傳回 true,否則傳回 false

測試 Term 是否為佇列,如果是,則傳回 true,否則傳回 false。請注意,即使不是由此模組建構的,此測試也會針對與佇列表示法一致的項傳回 true。另請參閱關於資料型別的註解。

傳回一個佇列 Q3,它是將 Q1Q2 連接在一起的結果,其中 Q1Q2 的前面。

計算並傳回佇列 Q 的長度。

如果 ItemQ 中的某些元素匹配,則傳回 true,否則傳回 false

傳回一個空佇列。

移除佇列 Q1 前端的項目。傳回元組 {{value, Item}, Q2},其中 Item 是已移除的項目,Q2 是結果佇列。如果 Q1 為空,則傳回元組 {empty, Q1}

移除佇列 Q1 後端的項目。傳回元組 {{value, Item}, Q2},其中 Item 是已移除的項目,Q2 是新的佇列。如果 Q1 為空,則傳回元組 {empty, Q1}

傳回一個佇列 Q2,其中包含 Q1 的項目,順序相反。

Q1 分成兩個。前 N 個項目會放入 Q2,其餘項目放入 Q3

傳回佇列中項目的列表,其順序相同;佇列的前端項目成為列表的頭部。

擴充 API

傳回一個佇列 Q2,它是從 Q1 中移除前端項目的結果。

傳回一個佇列 Q2,它是從 Q1 中移除後端項目的結果。

傳回佇列 Q 前端的 Item

傳回佇列 Q 後端的 Item

傳回元組 {value, Item},其中 ItemQ 的前端項目,如果 Q 為空,則傳回 empty

傳回元組 {value, Item},其中 ItemQ 的後端項目,如果 Q 為空,則傳回 empty

Okasaki API

Item 插入佇列 Q1 的頭部。傳回新的佇列 Q2

傳回佇列 Q 的尾部項目。

從佇列 Q 的頭部傳回 Item

傳回一個佇列 Q2,它是從 Q1 中移除尾部項目的結果。

lait(Q1) 已棄用

傳回一個佇列 Q2,它是從 Q1 中移除尾部項目的結果。

傳回佇列 Q 的尾部項目。

傳回一個佇列 Q2,它是從 Q1 中移除尾部項目的結果。

Item 作為佇列 Q1 的尾部項目插入。傳回新的佇列 Q2

傳回一個佇列 Q2,它是從 Q1 中移除頭部項目的結果。

型別

-type queue() :: queue(_).
-opaque queue(Item)

new/0 傳回。

原始 API

連結到此函式

all(Pred, Q)

檢視原始碼 (自 OTP 24.0 起)
-spec all(Pred, Q :: queue(Item)) -> boolean() when Pred :: fun((Item) -> boolean()).

如果 Pred(Item)Q 中的所有項目 Item 都傳回 true,則傳回 true,否則傳回 false

範例

1> Queue = queue:from_list([1,2,3,4,5]).
2> queue:all(fun (E) -> E > 3 end, Queue).
false
3> queue:all(fun (E) -> E > 0 end, Queue).
true
連結到此函式

any(Pred, Q)

檢視原始碼 (自 OTP 24.0 起)
-spec any(Pred, Q :: queue(Item)) -> boolean() when Pred :: fun((Item) -> boolean()).

如果 Pred(Item)Q 中至少一個項目 Item 傳回 true,則傳回 true,否則傳回 false

範例

1> Queue = queue:from_list([1,2,3,4,5]).
2> queue:any(fun (E) -> E > 10 end, Queue).
false
3> queue:any(fun (E) -> E > 3 end, Queue).
true
連結到此函式

delete(Item, Q1)

檢視原始碼 (自 OTP 24.0 起)
-spec delete(Item, Q1) -> Q2 when Item :: T, Q1 :: queue(T), Q2 :: queue(T), T :: term().

傳回 Q1 的副本,其中刪除第一個與 Item 匹配的項目(如果有的話)。

範例

1> Queue = queue:from_list([1,2,3,4,5]).
2> Queue1 = queue:delete(3, Queue).
3> queue:member(3, Queue1).
false
連結到此函式

delete_r(Item, Q1)

檢視原始碼 (自 OTP 24.0 起)
-spec delete_r(Item, Q1) -> Q2 when Item :: T, Q1 :: queue(T), Q2 :: queue(T), T :: term().

傳回 Q1 的副本,其中刪除最後一個與 Item 匹配的項目(如果有的話)。

範例

1> Queue = queue:from_list([1,2,3,4,3,5]).
2> Queue1 = queue:delete_r(3, Queue).
3> queue:to_list(Queue1).
[1,2,3,4,5]
連結到此函式

delete_with(Pred, Q1)

檢視原始碼 (自 OTP 24.0 起)
-spec delete_with(Pred, Q1) -> Q2
                     when
                         Pred :: fun((Item) -> boolean()),
                         Q1 :: queue(Item),
                         Q2 :: queue(Item),
                         Item :: term().

傳回 Q1 的副本,其中刪除第一個使 Pred 傳回 true 的項目(如果有的話)。

範例

1> Queue = queue:from_list([100,1,2,3,4,5]).
2> Queue1 = queue:delete_with(fun (E) -> E > 0, Queue).
3> queue:to_list(Queue1).
[1,2,3,4,5]
連結到此函式

delete_with_r(Pred, Q1)

檢視原始碼 (自 OTP 24.0 起)
-spec delete_with_r(Pred, Q1) -> Q2
                       when
                           Pred :: fun((Item) -> boolean()),
                           Q1 :: queue(Item),
                           Q2 :: queue(Item),
                           Item :: term().

傳回 Q1 的副本,其中刪除最後一個使 Pred 傳回 true 的項目(如果有的話)。

範例

1> Queue = queue:from_list([1,2,3,4,5,100]).
2> Queue1 = queue:delete_with(fun (E) -> E > 10, Queue).
3> queue:to_list(Queue1).
[1,2,3,4,5]
-spec filter(Fun, Q1 :: queue(Item)) -> Q2 :: queue(Item) when Fun :: fun((Item) -> boolean() | [Item]).

傳回一個佇列 Q2,它是對 Q1 中的所有項目呼叫 Fun(Item) 的結果。

如果 Fun(Item) 返回 trueItem 會被複製到結果佇列。如果它返回 falseItem 則不會被複製。如果它返回一個列表,列表中的元素會被插入到結果佇列中,而不是 Item

範例 1

1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue1 = queue:filter(fun (E) -> E > 2 end, Queue).
{[5],[3,4]}
3> queue:to_list(Queue1).
[3,4,5]

因此,Fun(Item) 返回 [Item] 在語義上等同於返回 true,就像返回 [] 在語義上等同於返回 false。但是返回列表會比返回原子產生更多的垃圾。

範例 2

1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue1 = queue:filter(fun (E) -> [E, E+1] end, Queue).
{[6,5,5,4,4,3],[1,2,2,3]}
3> queue:to_list(Queue1).
[1,2,2,3,3,4,4,5,5,6]
連結到此函式

filtermap(Fun, Q1)

檢視原始碼 (自 OTP 24.0 起)
-spec filtermap(Fun, Q1) -> Q2
                   when
                       Fun :: fun((Item) -> boolean() | {true, Value}),
                       Q1 :: queue(Item),
                       Q2 :: queue(Item | Value),
                       Item :: term(),
                       Value :: term().

傳回一個佇列 Q2,它是對 Q1 中的所有項目呼叫 Fun(Item) 的結果。

如果 Fun(Item) 返回 trueItem 會被複製到結果佇列。如果它返回 falseItem 則不會被複製。如果它返回 {true, NewItem},則此位置的佇列元素會被結果佇列中的 NewItem 取代。

範例 1

1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue1 = queue:filtermap(fun (E) -> E > 2 end, Queue).
{[5],[3,4]}
3> queue:to_list(Queue1).
[3,4,5]
4> Queue1 = queue:filtermap(fun (E) -> {true, E+100} end, Queue).
{"ihg","ef"}
5> queue:to_list(Queue1).
"efghi
連結到此函式

fold(Fun, Acc0, Q)

檢視原始碼 (自 OTP 24.0 起)
-spec fold(Fun, Acc0, Q :: queue(Item)) -> Acc1
              when
                  Fun :: fun((Item, AccIn) -> AccOut),
                  Acc0 :: term(),
                  Acc1 :: term(),
                  AccIn :: term(),
                  AccOut :: term().

Queue 的連續項目 Item 呼叫 Fun(Item, AccIn),從 AccIn == Acc0 開始。佇列會依佇列順序遍歷,即從前端到後端。Fun/2 必須傳回新的累加器,該累加器會傳遞到下一次呼叫。該函式傳回累加器的最終值。如果佇列為空,則會傳回 Acc0

範例

1> queue:fold(fun(X, Sum) -> X + Sum end, 0, queue:from_list([1,2,3,4,5])).
15
2> queue:fold(fun(X, Prod) -> X * Prod end, 1, queue:from_list([1,2,3,4,5])).
120
-spec from_list(L :: [Item]) -> queue(Item).

傳回一個包含 L 中項目的佇列,其順序相同;列表的頭部項目成為佇列的前端項目。

-spec in(Item, Q1 :: queue(Item)) -> Q2 :: queue(Item).

Item 插入佇列 Q1 的後端。傳回結果佇列 Q2

範例

1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue1 = queue:in(100, Queue).
{[100,5,4,3],[1,2]}
3> queue:to_list(Queue1).
[1,2,3,4,5,100]
-spec in_r(Item, Q1 :: queue(Item)) -> Q2 :: queue(Item).

Item 插入佇列 Q1 的前端。傳回結果佇列 Q2

範例

1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue1 = queue:in_r(100, Queue).
{[5,4,3],[100,1,2]}
3> queue:to_list(Queue1).
[100,1,2,3,4,5]
-spec is_empty(Q :: queue()) -> boolean().

測試 Q 是否為空,如果是,則傳回 true,否則傳回 false

-spec is_queue(Term :: term()) -> boolean().

測試 Term 是否為佇列,如果是,則傳回 true,否則傳回 false。請注意,即使不是由此模組建構的,此測試也會針對與佇列表示法一致的項傳回 true。另請參閱關於資料型別的註解。

-spec join(Q1 :: queue(Item), Q2 :: queue(Item)) -> Q3 :: queue(Item).

傳回一個佇列 Q3,它是將 Q1Q2 連接在一起的結果,其中 Q1Q2 的前面。

範例

1> Queue1 = queue:from_list([1,3]).
{[3],[1]}
2> Queue2 = queue:from_list([2,4]).
{[4],[2]}
3> queue:to_list(queue:join(Queue1, Queue2)).
[1,3,2,4]
-spec len(Q :: queue()) -> non_neg_integer().

計算並傳回佇列 Q 的長度。

-spec member(Item, Q :: queue(Item)) -> boolean().

如果 ItemQ 中的某些元素匹配,則傳回 true,否則傳回 false

-spec new() -> queue(none()).

傳回一個空佇列。

-spec out(Q1 :: queue(Item)) -> {{value, Item}, Q2 :: queue(Item)} | {empty, Q1 :: queue(Item)}.

移除佇列 Q1 前端的項目。傳回元組 {{value, Item}, Q2},其中 Item 是已移除的項目,Q2 是結果佇列。如果 Q1 為空,則傳回元組 {empty, Q1}

範例

1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> {{value, 1=Item}, Queue1} = queue:out(Queue).
{{value,1},{[5,4,3],[2]}}
3> queue:to_list(Queue1).
[2,3,4,5]
-spec out_r(Q1 :: queue(Item)) -> {{value, Item}, Q2 :: queue(Item)} | {empty, Q1 :: queue(Item)}.

移除佇列 Q1 後端的項目。傳回元組 {{value, Item}, Q2},其中 Item 是已移除的項目,Q2 是新的佇列。如果 Q1 為空,則傳回元組 {empty, Q1}

範例

1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> {{value, 5=Item}, Queue1} = queue:out_r(Queue).
{{value,5},{[4,3],[1,2]}}
3> queue:to_list(Queue1).
[1,2,3,4]
-spec reverse(Q1 :: queue(Item)) -> Q2 :: queue(Item).

傳回一個佇列 Q2,其中包含 Q1 的項目,順序相反。

-spec split(N :: non_neg_integer(), Q1 :: queue(Item)) -> {Q2 :: queue(Item), Q3 :: queue(Item)}.

Q1 分成兩個。前 N 個項目會放入 Q2,其餘項目放入 Q3

-spec to_list(Q :: queue(Item)) -> [Item].

傳回佇列中項目的列表,其順序相同;佇列的前端項目成為列表的頭部。

範例

1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> List == queue:to_list(Queue).
true

擴展 API

-spec drop(Q1 :: queue(Item)) -> Q2 :: queue(Item).

傳回一個佇列 Q2,它是從 Q1 中移除前端項目的結果。

如果 Q1 為空,則會因 empty 的原因而失敗。

範例

1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue = queue:drop(Queue).
{[5,4,3],[2]}
3> queue:to_list(Queue1).
[2,3,4,5]
-spec drop_r(Q1 :: queue(Item)) -> Q2 :: queue(Item).

傳回一個佇列 Q2,它是從 Q1 中移除後端項目的結果。

如果 Q1 為空,則會因 empty 的原因而失敗。

範例

1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue = queue:drop_r(Queue).
{[4,3],[1,2]}
3> queue:to_list(Queue1).
[1,2,3,4]
-spec get(Q :: queue(Item)) -> Item.

傳回佇列 Q 前端的 Item

如果 Q 為空,則會因 empty 的原因而失敗。

範例 1

1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> 1 == queue:get(Queue).
true
-spec get_r(Q :: queue(Item)) -> Item.

傳回佇列 Q 後端的 Item

如果 Q 為空,則會因 empty 的原因而失敗。

範例 1

1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> 5 == queue:get_r(Queue).
true
-spec peek(Q :: queue(Item)) -> empty | {value, Item}.

傳回元組 {value, Item},其中 ItemQ 的前端項目,如果 Q 為空,則傳回 empty

範例 1

1> queue:peek(queue:new()).
empty
2> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
3> queue:peek(Queue).
{value, 1}
-spec peek_r(Q :: queue(Item)) -> empty | {value, Item}.

傳回元組 {value, Item},其中 ItemQ 的後端項目,如果 Q 為空,則傳回 empty

範例 1

1> queue:peek_r(queue:new()).
empty
2> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
3> queue:peek_r(Queue).
{value, 5}

Okasaki API

-spec cons(Item, Q1 :: queue(Item)) -> Q2 :: queue(Item).

Item 插入佇列 Q1 的頭部。傳回新的佇列 Q2

範例

1> Queue = queue:cons(0, queue:from_list([1,2,3])).
{[3,2],[0,1]}
2> queue:to_list(Queue).
[0,1,2,3]
-spec daeh(Q :: queue(Item)) -> Item.

傳回佇列 Q 的尾部項目。

如果 Q 為空,則會因 empty 的原因而失敗。

範例 1

1> queue:daeh(queue:from_list([1,2,3])).
3
-spec head(Q :: queue(Item)) -> Item.

從佇列 Q 的頭部傳回 Item

如果 Q 為空,則會因 empty 的原因而失敗。

範例 1

1> queue:head(queue:from_list([1,2,3])).
1
-spec init(Q1 :: queue(Item)) -> Q2 :: queue(Item).

傳回一個佇列 Q2,它是從 Q1 中移除尾部項目的結果。

如果 Q1 為空,則會因 empty 的原因而失敗。

範例

1> Queue = queue:init(queue:from_list([1,2,3])).
{[2],[1]}
2> queue:to_list(Queue).
[1,2]
此函數已過時。queue:lait/1 已過時;請改用 queue:liat/1。
-spec lait(Q1 :: queue(Item)) -> Q2 :: queue(Item).

傳回一個佇列 Q2,它是從 Q1 中移除尾部項目的結果。

如果 Q1 為空,則會因 empty 的原因而失敗。

名稱 lait/1 是拼寫錯誤 - 請不要再使用它。

-spec last(Q :: queue(Item)) -> Item.

傳回佇列 Q 的尾部項目。

如果 Q 為空,則會因 empty 的原因而失敗。

範例

1> queue:last(queue:from_list([1,2,3])).
3
-spec liat(Q1 :: queue(Item)) -> Q2 :: queue(Item).

傳回一個佇列 Q2,它是從 Q1 中移除尾部項目的結果。

如果 Q1 為空,則會因 empty 的原因而失敗。

範例

1> Queue = queue:liat(queue:from_list([1,2,3])).
{[2],[1]}
2> queue:to_list(Queue).
[1,2]
-spec snoc(Q1 :: queue(Item), Item) -> Q2 :: queue(Item).

Item 作為佇列 Q1 的尾部項目插入。傳回新的佇列 Q2

範例

1> Queue = queue:snoc(queue:from_list([1,2,3]), 4).
{[4,3,2],[1]}
2> queue:to_list(Queue).
[1,2,3,4]
-spec tail(Q1 :: queue(Item)) -> Q2 :: queue(Item).

傳回一個佇列 Q2,它是從 Q1 中移除頭部項目的結果。

如果 Q1 為空,則會因 empty 的原因而失敗。