Thiel
1
Hi guys,
I am trying to use an Queue with Agents in the next program:
defmodule TestMyQueue do
require EQueue
@times 1..100
collection = EQueue.new()
{:ok, queue} = Agent.start_link fn -> collection end
Enum.each(@times, fn item ->
case rem(item, 5) == 0 do
true -> pop_agent(queue)
false -> Agent.update(queue, &push(&1, item))
end
end)
Agent.stop(queue)
defp pop([]), do: {:empty, []}
defp pop([h|t] = from) when is_list(from), do: {:value, h, t}
defp pop(queue = %EQueue{}), do: EQueue.pop(queue)
defp pop_agent(agent), do: Agent.get_and_update(agent, fn state ->
case pop(state) do
{:value, item, queue} -> {item, queue}
{:empty, queue} -> {:empty, queue}
end
end)
defp push(collection, item) when is_list(collection), do: collection ++ [item]
defp push(collection = %EQueue{}, item), do: EQueue.push(collection, item)
end
and I get the next compilation error: (CompileError) lib/tst.ex:29: undefined function pop_agent/1
Can anyone explain what I am doing wrong?
Thanks in advance,
Thiel Chang
idi527
2
Maybe it’s because you call pop_agent
before you define it? Compilation happens from top to bottom, I think.
Could you explain what you are trying to achieve with
require EQueue
@times 1..100
collection = EQueue.new()
{:ok, queue} = Agent.start_link fn -> collection end
Enum.each(@times, fn item ->
case rem(item, 5) == 0 do
true -> pop_agent(queue)
false -> Agent.update(queue, &push(&1, item))
end
end)
Agent.stop(queue)
I don’t see it produce any side effects on the module.
I’m going to answer this from a purely technical perspective.
Lines 7 - 18 are run at compile-time. pop_agent/1
won’t exist at the point it’s invoked.
So @idi527 is correct there.
You probably want to put lines 7 - 18 in a function?
1 Like
Thiel
4
Hi guys,
You were all right. I redefined the External and Internal APIś and now it works!
defmodule EQueTest do
use ExUnit.Case
require EQueue
@name __MODULE__
# External API's
def start_link(queue) do
Agent.start_link(fn -> queue end)
end
def start_link(queue, @name) do
Agent.start_link(fn -> queue end, name: @name)
end
def push_item(queue,item) do
Agent.update(queue, &push(&1, item))
end
def pop_item(queue), do: Agent.get_and_update(queue, fn state ->
case pop(state) do
{:value, item, queue} -> {item, queue}
{:empty, queue} -> {:empty, queue}
end
end)
# Internal API's
defp push(collection, item) when is_list(collection), do: collection ++ [item]
defp push(collection = %EQueue{}, item), do: EQueue.push(collection, item)
defp pop([]), do: {:empty, []}
defp pop([h|t] = from) when is_list(from), do: {:value, h, t}
defp pop(queue = %EQueue{}), do: EQueue.pop(queue)
test "Test EQueue's push and pop" do
{_result, queue} = start_link(EQueue.new())
push_item(queue, 1)
push_item(queue, 2)
assert pop_item(queue) == 1
end
end
Many thanks,
Thiel Chang
1 Like