[erlang-questions] erlang-questions Digest, Vol 15, Issue 86

John Hughes <>
Tue Aug 26 09:01:18 CEST 2008


>
> Ok, based on your suggestions, here is what I have.
>
> Eshell V5.5.5  (abort with ^G)
> 1> Q1 = queue:new().
> {[],[]}
> 2> Q2 = queue:in("foo", Q1).
> {["foo"],[]}
> 3> Q3 = queue:in("bar", Q2).
> {["bar"],["foo"]}
> 4> Q4 = queue:in("blah", Q3).
> {["blah","bar"],["foo"]}
> 5> Q5 = queue:in("stuff", Q4).
> {["stuff","blah","bar"],["foo"]}
> 6> Q6 = queue:out(Q5).
> {{value,"foo"},{["stuff","blah"],["bar"]}}

If you look at the value of Q6, you'll see it's different in structure from 
the previous queues you created. And indeed, it's not a queue. The 
documentation says:

    out(Q1) -> Result

    Types:

    Result = {{value, Item}, Q2} | {empty, Q1}
    Q1 = Q2 = queue()

    Removes the head item from the queue Q1. Returns the tuple {{value, 
Item}, Q2}, where Item is the item removed and Q2 is the new queue. If Q1 is 
empty, the tuple {empty, Q1} is returned.

queue:out(Q) removes an element from the queue, but because it cannot 
*modify* the original queue (no side-effects, remember?), then it must 
return *both* the element it removed, and the remainder of the queue, as its 
result. That's what happened above: you removed "foo" (in the first 
component of the result), and the remaining queue contains "stuff", "blah" 
and "bar" (in the second component).

The reason that the first component is {value,"foo"} and not just "foo" is 
that the queue might have been empty, in which case no element can be 
removed. queue:out returns empty as the element in that case. Of course, the 
queue might actually contain the atom empty as one of its elements. To 
ensure that this case can't be confused with an empty queue, queue:out tags 
real queue elements with the value tag, as you see above--so if we did 
remove an element empty from a queue, then the first component of the result 
would be {value,empty}, not empty.

So, if you want to remove an element from a queue (and you know for sure 
that the queue is not empty), then instead of

Q6 = queue:out(Q5).

you should write

{{value,X},Q6} = queue:out(Q5).

Then X will be bound to the element ("foo" in this case), and the code below 
will work. What the error report means, by the way, is that you passed a bad 
argument to queue:in--and it was the pair {{value,"foo"}...}, which was 
expected to be a queue, but wasn't.

> 7> Q7 = queue:in("stuff1", Q6).
>
> =ERROR REPORT==== 25-Aug-2008::20:23:40 ===
> Error in process <0.31.0> with exit value: {badarg,[{queue,in,
> ["stuff1",{{value,"foo"},{["stuff","blah"],["bar"]}}]},
> {erl_eval,do_apply,5},{erl_eval,expr,5},{shell,exprs,6},
> {shell,eval_loop,3}]}
>
> ** exited: {badarg,[{queue,in,
>                           ["stuff1",
>                            {{value,"foo"},{["stuff","blah"],
> ["bar"]}}]},
>                    {erl_eval,do_apply,5},
>                    {erl_eval,expr,5},
>                    {shell,exprs,6},
>                    {shell,eval_loop,3}]} **
>

By the way, the queue representations used by the queue module are always 
pairs of lists of elements, so if you see something different, you know it's 
not a queue.

John 




More information about the erlang-questions mailing list