Skip to content

Commit

Permalink
Add ordered_iterator function
Browse files Browse the repository at this point in the history
Some of the Enum's functions assume an ordering is defined for the collection.
Since ordering is not defined for all types, using `ordered_iterator`
allows us to raise a runtime error for those types.
  • Loading branch information
alco committed Apr 26, 2012
1 parent d79ba92 commit 2c4f17f
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 69 deletions.
26 changes: 16 additions & 10 deletions lib/enum.ex
Expand Up @@ -114,7 +114,7 @@ defmodule Enum do
"""
def drop(collection, count) do
{ iterator, pointer } = I.iterator(collection)
{ iterator, pointer } = I.ordered_iterator(collection)
drop(iterator, pointer, count)
end

Expand All @@ -131,7 +131,7 @@ defmodule Enum do
#=> [3,4,5]
"""
def drop_while(collection, fun) do
{ iterator, pointer } = I.iterator(collection)
{ iterator, pointer } = I.ordered_iterator(collection)
drop_while(iterator, pointer, fun)
end

Expand Down Expand Up @@ -302,7 +302,7 @@ defmodule Enum do
"""
def join(collection, joiner // "") do
{ iterator, pointer } = I.iterator(collection)
{ iterator, pointer } = I.ordered_iterator(collection)
join(iterator, pointer, joiner)
end

Expand Down Expand Up @@ -453,7 +453,7 @@ defmodule Enum do
"""
def split(collection, count) do
{ iterator, pointer } = I.iterator(collection)
{ iterator, pointer } = I.ordered_iterator(collection)
split(iterator, pointer, count)
end

Expand All @@ -470,7 +470,7 @@ defmodule Enum do
#=> { [1], [2, 3, 4] }
"""
def split_with(collection, fun) do
{ iterator, pointer } = I.iterator(collection)
{ iterator, pointer } = I.ordered_iterator(collection)
split_with(iterator, pointer, fun)
end

Expand All @@ -489,7 +489,7 @@ defmodule Enum do
"""
def take(collection, count) do
{ iterator, pointer } = I.iterator(collection)
{ iterator, pointer } = I.ordered_iterator(collection)
take(iterator, pointer, count)
end

Expand All @@ -507,7 +507,7 @@ defmodule Enum do
"""
def take_while(collection, fun // fn(x, do: x)) do
{ iterator, pointer } = I.iterator(collection)
{ iterator, pointer } = I.ordered_iterator(collection)
take_while(iterator, pointer, fun)
end

Expand Down Expand Up @@ -848,6 +848,8 @@ end
defimpl Enum.Iterator, for: List do
def iterator(list), do: { iterate(&1), iterate({ list, fn(list, do: list) }) }

def ordered_iterator(list), do: iterator(list)

def to_list(list), do: list

def iterate({ [h|t], ctor }) do
Expand All @@ -868,9 +870,13 @@ end
defimpl Enum.Iterator, for: Tuple do
import Enum.Iterator.List, only: [iterate: 1]

def iterator(dict), do: { iterate(&1),
iterate({ to_list(dict),
fn(pairs, do: extend(PDict.empty(dict), pairs)) }) }
def iterator(dict) do
{ iterate(&1), iterate({ to_list(dict), fn(pairs, do: extend(PDict.empty(dict), pairs)) }) }
end

def ordered_iterator(_) do
raise ArgumentError, message: "Dict does not support ordering"
end

def to_list(dict), do: PDict.to_list(dict)

Expand Down
98 changes: 39 additions & 59 deletions test/elixir/enum_test.exs
Expand Up @@ -202,21 +202,17 @@ defmodule EnumTest.Dict do
refute Enum.any?(Dict.new)
end

# test :drop do
# assert_equal [1,2,3], Enum.drop [1,2,3], 0
# assert_equal [2,3], Enum.drop [1,2,3], 1
# assert_equal [3], Enum.drop [1,2,3], 2
# assert_equal [], Enum.drop [1,2,3], 3
# assert_equal [], Enum.drop [1,2,3], 4
# assert_equal [], Enum.drop [], 3
# end
#
# test :drop_while do
# assert_equal [4,3,2,1], Enum.drop_while [1,2,3,4,3,2,1], fn(x, do: x <= 3)
# assert_equal [1,2,3], Enum.drop_while [1,2,3], fn(_, do: false)
# assert_equal [], Enum.drop_while [1,2,3], fn(x, do: x <= 3)
# assert_equal [], Enum.drop_while [], fn(_, do: false)
# end
test :drop do
assert_raises ArgumentError, fn ->
Enum.drop Dict.new, 5
end
end

test :drop_while do
assert_raises ArgumentError, fn ->
Enum.drop_while Dict.new, fn(x, do: x)
end
end

test :find do
dict = Dict.new [:a, :b, :c], [1, 2, 3]
Expand Down Expand Up @@ -291,18 +287,11 @@ defmodule EnumTest.Dict do
assert_equal 7, Enum.reduce(dict, 1, fn({_, v}, acc, do: v + acc))
end

# test :join_with_bin do
# assert_equal "", Enum.join([], " = ")
# assert_equal "1 = 2 = 3", Enum.join([1,2,3], " = ")
# assert_equal "1 = 2 = 3", Enum.join([1,"2",3], " = ")
# assert_equal "123", Enum.join([1,2,3])
# end
#
# test :join_with_list do
# assert_equal '', Enum.join([], ' = ')
# assert_equal '1 = 2 = 3', Enum.join([1,2,3], ' = ')
# assert_equal '1 = 2 = 3', Enum.join([1,"2",3], ' = ')
# end
test :join do
assert_raises ArgumentError, fn ->
Enum.join Dict.new, ""
end
end

test :keyfind do
dict = Dict.new [a: 1, b: 2, c: 3]
Expand Down Expand Up @@ -332,36 +321,27 @@ defmodule EnumTest.Dict do
assert_equal { dict, Dict.new }, Enum.partition(dict, fn({_k, v}, do: v < 10))
end

# test :split do
# assert_equal { [], [1,2,3] }, Enum.split [1,2,3], 0
# assert_equal { [1], [2,3] }, Enum.split [1,2,3], 1
# assert_equal { [1,2], [3] }, Enum.split [1,2,3], 2
# assert_equal { [1,2,3], [] }, Enum.split [1,2,3], 3
# assert_equal { [1,2,3], [] }, Enum.split [1,2,3], 4
# assert_equal { [], [] }, Enum.split [], 3
# end
#
# test :split_with do
# assert_equal { [1,2,3], [] }, Enum.split_with [1,2,3], fn(_, do: false)
# assert_equal { [], [1,2,3] }, Enum.split_with [1,2,3], fn(_, do: true)
# assert_equal { [1,2], [3] }, Enum.split_with [1,2,3], fn(x, do: x > 2)
# assert_equal { [1,2,3], [] }, Enum.split_with [1,2,3], fn(x, do: x > 3)
# assert_equal { [], [] }, Enum.split_with [], fn(_, do: true)
# end
#
# test :take do
# assert_equal [], Enum.take [1,2,3], 0
# assert_equal [1], Enum.take [1,2,3], 1
# assert_equal [1,2], Enum.take [1,2,3], 2
# assert_equal [1,2,3], Enum.take [1,2,3], 3
# assert_equal [1,2,3], Enum.take [1,2,3], 4
# assert_equal [], Enum.take [], 3
# end
#
# test :take_while do
# assert_equal [], Enum.take_while [1,2,3], fn(x, do: x > 3)
# assert_equal [1], Enum.take_while [1,2,3], fn(x, do: x <= 1)
# assert_equal [1,2,3], Enum.take_while [1,2,3], fn(x, do: x <= 3)
# assert_equal [], Enum.take_while [], fn(_, do: true)
# end
test :split do
assert_raises ArgumentError, fn ->
Enum.split Dict.new, 5
end
end

test :split_with do
assert_raises ArgumentError, fn ->
Enum.split_with Dict.new, fn(x, do: x)
end
end

test :take do
assert_raises ArgumentError, fn ->
Enum.take Dict.new, 5
end
end

test :take_while do
assert_raises ArgumentError, fn ->
Enum.take_while Dict.new, fn(x, do: x)
end
end
end

0 comments on commit 2c4f17f

Please sign in to comment.