Can anyone advice how to solve the next problem in this program:
defmodule QueueLoader do
require Wdata
{_result, queue} = Wdata.start_link(EQueue.new())
# Put the list items in the queue
Enum.each([1,2,3,4,5], fn item -> Wdata.add_agent(queue,item) end)
# Pop 3 items from the queue
for item <- 1..3 , do: Wdata.pop_agent(queue) # Ok, this works.
# Returns a list of the items in the queue in the same order;
# the front item of the queue must become the head of the list
EQueue.to_list(queue) |> IO.inspect()
end
When I compile this program it gives the next compilation error.
== Compilation error in file lib/queue3.ex ==
** (FunctionClauseError) no function clause matching in EQueue.to_list/1
The following arguments were given to EQueue.to_list/1:
# 1
#PID<0.94.0>
Attempted function clauses (showing 1 out of 1):
def to_list(%EQueue{data: queue})
lib/e_queue.ex:83: EQueue.to_list/1
lib/queue3.ex:56: (module)
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
So I understand the PID refers to a process
Here follows the struct and spec:
defstruct data: :queue.new
@type t :: %EQueue{data: {[any],[any]} }
@doc """
Returns a list of the items in the queue in the same order;
the front item of the queue will become the head of the list.
## Example
iex> EQueue.from_list([1, 2, 3, 4, 5]) |> EQueue.to_list
[1, 2, 3, 4, 5]
"""
@spec to_list(EQueue.t) :: [any]
def to_list(%EQueue{data: queue}), do: :queue.to_list(queue)
Thanks for your quick response. Yes, I am playing with EQueue.
I have used your suggestion and made a little test program. It works but not really good as I expected. The reason is that I don’t know how to get the state of the EQueue.
I used - pop(state) - to get a state, but as a side effect of the pop statement the list lacks one element of the original list [1…10].
test "Test state of the queue" do
# @times 1..10
{:ok, queue} = Agent.start_link fn -> EQueue.new end
Enum.each(@times, fn item -> push_item(queue, item)
end)
{item, state} = Agent.get(queue, fn state -> case pop(state) do
{:value, item, queue} -> {item, queue}
end
end)
# The value of state is: #EQueue<[2, 3, 4, 5, 6, 7, 8, 9, 10]>
assert EQueue.length(state) == 9
assert state |> EQueue.to_list == [2, 3, 4, 5, 6, 7, 8, 9, 10]
assert Enum.sum(EQueue.to_list(state)) == 54
Agent.stop(queue)
end
So, how do I get the state of the module EQueue; or a module in general?
No, the equeu is the state of your agent. You shall retrieve that, should roughly be like Agent.get(pid, & &1). And that is your queue you can convert to a list.
Also why are you having the agent in-between? Why aren’t you playing with the queue until you get it and only then wrap it in an agent until you get the concept of agents? It’s easier to learn a thing at time rather than 2.
Yes, Agent.get(pid, & &1) is the right solution to get the queue state.
I always appreciate your excellent advice and comments in the Elixir forum!
In my case they are a pleasure in learning Elixir.
As a retired software engineer I remember the software engineering class in learning the queue subject. (Now more than 50 years ago e.g Knuth's Fundamental