Skip to content

Commit cb32338

Browse files
author
José Valim
committed
Merge pull request #1922 from elixir-lang/jv-iteratees
Migrate Enumerable to use an iteratees based solution
2 parents 898e01c + cf9284f commit cb32338

File tree

16 files changed

+1865
-986
lines changed

16 files changed

+1865
-986
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
* [Kernel] Implement `defmodule/2`, `@/1`, `def/2` and friends in Elixir itself. `case/2`, `try/2` and `receive/1` have been made special forms. `var!/1`, `var!/2` and `alias!/1` have also been implemented in Elixir and demoted from special forms
88
* [Record] Support dynamic fields in `defrecordp`
99
* [Stream] Add `Stream.resource/3`
10+
* [Stream] Add `Stream.zip/2`, `Stream.filter_map/3`, `Stream.each/2`, `Stream.take_every/2`, `Stream.chunks/2`, `Stream.chunks/3`, `Stream.chunks/4`, `Stream.chunks_by/2`, `Stream.scan/2`, `Stream.scan/3` and `Stream.uniq/2`
11+
* [Stream] Support `Stream.take/2` and `Stream.drop/2` with negative counts
1012
* [Typespec] Support `is_var/1` in typespecs
1113

1214
* Bug fixes
@@ -16,13 +18,17 @@
1618
* [Mix] Also symlink `include` directories in _build dependencies
1719

1820
* Deprecations
21+
* [Enum] `Enumerable.count/1` and `Enumerable.member?/2` should now return tagged tuples. Please see `Enumerable` docs for more info
1922
* [File] `File.binstream!/3` is deprecated. Simply use `File.stream!/3` which is able to figure out if `stream` or `binstream` operations should be used
2023
* [Macro] `Macro.extract_args/1` is deprecated in favor of `Macro.decompose_call/1`
2124
* [Typespec] `when` clauses in typespecs were moved to the outer part of the spec
2225

2326
* Backwards incompatible changes
24-
* [Kernel] Behaviour of `Enum.drop/2` and `Enum.take/2` has been switched when given negative counts
27+
* [Enum] Behaviour of `Enum.drop/2` and `Enum.take/2` has been switched when given negative counts
28+
* [Enum] Behaviour of `Enum.zip/2` has been changed to stop as soon as the first enumerable finishes
29+
* [Enum] `Enumerable.reduce/3` protocol has changed to support suspension. Please see `Enumerable` docs for more info
2530
* [Mix] Require `:escript_main_module` to be set before generating escripts
31+
* [Range] `Range.Iterator` protocol has changed in order to work with the new `Enumerable.reduce/3`. Please see `Range.Iterator` docs for more info
2632
* [Stream] The `Stream.Lazy` structure has changed to accumulate functions and accumulators as we go (its inspected representation has also changed)
2733

2834
# v0.11.2 (2013-11-14)

lib/elixir/lib/dict.ex

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ defmodule Dict do
7070
defcallback update(t, key, value, (value -> value)) :: t
7171
defcallback update!(t, key, (value -> value)) :: t | no_return
7272
defcallback values(t) :: list(value)
73-
defcallback reduce(t, any, ({key, value}, any -> any)) :: any
7473

7574
defmacrop target(dict) do
7675
quote do

lib/elixir/lib/dict/behaviour.ex

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,37 +48,31 @@ defmodule Dict.Behaviour do
4848
:error -> default
4949
end
5050
end
51-
defoverridable get: 2, get: 3
5251

5352
def fetch!(dict, key) do
5453
case fetch(dict, key) do
5554
{ :ok, value } -> value
56-
:error -> raise(KeyError, key: key)
55+
:error -> raise KeyError, key: key
5756
end
5857
end
59-
defoverridable fetch!: 2
6058

6159
def has_key?(dict, key) do
6260
match? { :ok, _ }, fetch(dict, key)
6361
end
64-
defoverridable has_key?: 2
6562

6663
def put_new(dict, key, value) do
6764
update(dict, key, value, fn(v) -> v end)
6865
end
69-
defoverridable put_new: 3
7066

7167
def drop(dict, []), do: dict
7268

7369
def drop(dict, [key|keys]) do
7470
drop(delete(dict, key), keys)
7571
end
76-
defoverridable drop: 2
7772

7873
def take(dict, keys) do
7974
take(dict, keys, new)
8075
end
81-
defoverridable take: 2
8276

8377
defp take(_dict, [], acc), do: acc
8478
defp take(dict, [key|keys], acc) do
@@ -88,38 +82,48 @@ defmodule Dict.Behaviour do
8882
end
8983
end
9084

91-
def to_list(dict), do: reduce(dict, [], &[&1|&2]) |> Enum.reverse
92-
defoverridable to_list: 1
85+
def to_list(dict) do
86+
reduce(dict, { :cont, [] }, fn
87+
kv, acc -> { :cont, [kv|acc] }
88+
end) |> elem(1) |> :lists.reverse
89+
end
9390

94-
def keys(dict), do: reduce(dict, [], fn({k, _}, acc) -> [k | acc] end) |> Enum.reverse
95-
defoverridable keys: 1
91+
def keys(dict) do
92+
reduce(dict, { :cont, [] }, fn
93+
{k, _}, acc -> { :cont, [k|acc] }
94+
end) |> elem(1) |> :lists.reverse
95+
end
9696

97-
def values(dict), do: reduce(dict, [], fn({_, v}, acc) -> [v | acc] end) |> Enum.reverse
98-
defoverridable values: 1
97+
def values(dict) do
98+
reduce(dict, { :cont, [] }, fn
99+
{_, v}, acc -> { :cont, [v|acc] }
100+
end) |> elem(1) |> :lists.reverse
101+
end
99102

100103
def equal?(dict1, dict2) do
101104
import Kernel, except: [size: 1]
102105
case size(dict1) == size(dict2) do
103106
false -> false
104-
true ->
105-
try do
106-
reduce(dict1, nil, fn({ k, v }, _acc) ->
107-
unless fetch(dict2, k) == { :ok, v }, do: throw(:error)
108-
end)
109-
true
110-
catch
111-
:error -> false
112-
end
107+
true ->
108+
reduce(dict1, { :cont, true }, fn({ k, v }, _acc) ->
109+
unless fetch(dict2, k) == { :ok, v } do
110+
{ :halt, false }
111+
else
112+
{ :cont, true }
113+
end
114+
end) |> elem(1)
113115
end
114116
end
115-
defoverridable equal?: 2
116117

117118
def merge(dict, enumerable, callback // fn(_k, _v1, v2) -> v2 end) do
118119
Enum.reduce(enumerable, dict, fn({key, value}, acc) ->
119120
update(acc, key, value, fn(v1) -> callback.(key, v1, value) end)
120121
end)
121122
end
122-
defoverridable merge: 2, merge: 3
123+
124+
defoverridable merge: 2, merge: 3, equal?: 2, to_list: 1, keys: 1,
125+
values: 1, take: 2, drop: 2, get: 2, get: 3, fetch!: 2,
126+
has_key?: 2, put_new: 3
123127
end
124128
end
125129
end

0 commit comments

Comments
 (0)