Skip to content

Commit a8564a7

Browse files
author
José Valim
committed
Deprecate functions as collectable
1 parent e2bac56 commit a8564a7

File tree

5 files changed

+49
-30
lines changed

5 files changed

+49
-30
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
* [URI] `to_string/1` now properly converts URI to strings when the schema is missing
2929

3030
* Deprecations
31+
* [Collectable] Having a function as collectable is deprecated
3132
* [Module] `Module.function/3` is deprecated, please use `:erlang.make_fun/3` instead
3233

3334
* Backwards incompatible changes

lib/elixir/lib/collectable.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ defimpl Collectable, for: Function do
9898
end
9999

100100
def into(function) do
101+
IO.write :stderr, "warning: passing a function as Collectable is deprecated\n#{Exception.format_stacktrace}"
101102
{function, function}
102103
end
103104
end

lib/elixir/test/elixir/enum_test.exs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,6 @@ defmodule EnumTest.List do
189189
assert Enum.into([a: 1, b: 2], %{c: 3}) == %{a: 1, b: 2, c: 3}
190190
assert Enum.into(%{a: 1, b: 2}, []) == [a: 1, b: 2]
191191
assert Enum.into([1, 2, 3], "numbers: ", &to_string/1) == "numbers: 123"
192-
assert Enum.into([1, 2, 3], fn
193-
func, {:cont, x} when is_function(func) -> [x]
194-
list, {:cont, x} -> [x|list]
195-
list, _ -> list
196-
end) == [3, 2, 1]
197192
end
198193

199194
test :intersperse do

lib/elixir/test/elixir/kernel/comprehension_test.exs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,25 @@ defmodule Kernel.ComprehensionTest do
66
import ExUnit.CaptureIO
77
require Integer
88

9+
defmodule PDict do
10+
defstruct []
11+
12+
defimpl Collectable do
13+
def empty(struct) do
14+
struct
15+
end
16+
17+
def into(struct) do
18+
{struct,
19+
fn
20+
_, {:cont, x} -> Process.put(:into_cont, [x|Process.get(:into_cont)])
21+
_, :done -> Process.put(:into_done, true)
22+
_, :halt -> Process.put(:into_halt, true)
23+
end}
24+
end
25+
end
26+
end
27+
928
defp to_bin(x) do
1029
<< x >>
1130
end
@@ -86,7 +105,7 @@ defmodule Kernel.ComprehensionTest do
86105
Process.put(:into_done, false)
87106
Process.put(:into_halt, false)
88107

89-
for x <- 1..3, into: collectable_pdict do
108+
for x <- 1..3, into: %PDict{} do
90109
x * 2
91110
end
92111

@@ -101,7 +120,7 @@ defmodule Kernel.ComprehensionTest do
101120
Process.put(:into_halt, false)
102121

103122
catch_error(
104-
for x <- 1..3, into: collectable_pdict do
123+
for x <- 1..3, into: %PDict{} do
105124
if x > 2, do: raise("oops"), else: x
106125
end
107126
)
@@ -114,21 +133,13 @@ defmodule Kernel.ComprehensionTest do
114133
test "for comprehension with into, generators and filters" do
115134
Process.put(:into_cont, [])
116135

117-
for x <- 1..3, Integer.odd?(x), << y <- "hello" >>, into: collectable_pdict do
136+
for x <- 1..3, Integer.odd?(x), << y <- "hello" >>, into: %PDict{} do
118137
x + y
119138
end
120139

121140
assert IO.iodata_to_binary(Process.get(:into_cont)) == "roohkpmmfi"
122141
end
123142

124-
defp collectable_pdict do
125-
fn
126-
_, {:cont, x} -> Process.put(:into_cont, [x|Process.get(:into_cont)])
127-
_, :done -> Process.put(:into_done, true)
128-
_, :halt -> Process.put(:into_halt, true)
129-
end
130-
end
131-
132143
## List generators (inlined by the compiler)
133144

134145
test "list for comprehensions" do

lib/elixir/test/elixir/stream_test.exs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,25 @@ Code.require_file "test_helper.exs", __DIR__
33
defmodule StreamTest do
44
use ExUnit.Case, async: true
55

6+
defmodule PDict do
7+
defstruct []
8+
9+
defimpl Collectable do
10+
def empty(struct) do
11+
struct
12+
end
13+
14+
def into(struct) do
15+
{struct,
16+
fn
17+
_, {:cont, x} -> Process.put(:stream_cont, [x|Process.get(:stream_cont)])
18+
_, :done -> Process.put(:stream_done, true)
19+
_, :halt -> Process.put(:stream_halt, true)
20+
end}
21+
end
22+
end
23+
end
24+
625
test "streams as enumerables" do
726
stream = Stream.map([1,2,3], &(&1 * 2))
827

@@ -297,15 +316,15 @@ defmodule StreamTest do
297316
Process.put(:stream_done, false)
298317
Process.put(:stream_halt, false)
299318

300-
stream = Stream.into([1, 2, 3], collectable_pdict)
319+
stream = Stream.into([1, 2, 3], %PDict{})
301320

302321
assert is_lazy(stream)
303322
assert Stream.run(stream) == :ok
304323
assert Process.get(:stream_cont) == [3,2,1]
305324
assert Process.get(:stream_done)
306325
refute Process.get(:stream_halt)
307326

308-
stream = Stream.into(fn _, _ -> raise "error" end, collectable_pdict)
327+
stream = Stream.into(fn _, _ -> raise "error" end, %PDict{})
309328
catch_error(Stream.run(stream))
310329
assert Process.get(:stream_halt)
311330
end
@@ -315,7 +334,7 @@ defmodule StreamTest do
315334
Process.put(:stream_done, false)
316335
Process.put(:stream_halt, false)
317336

318-
stream = Stream.into([1, 2, 3], collectable_pdict, fn x -> x*2 end)
337+
stream = Stream.into([1, 2, 3], %PDict{}, fn x -> x*2 end)
319338

320339
assert is_lazy(stream)
321340
assert Enum.to_list(stream) == [1, 2, 3]
@@ -329,7 +348,7 @@ defmodule StreamTest do
329348
Process.put(:stream_done, false)
330349
Process.put(:stream_halt, false)
331350

332-
stream = Stream.into([1, 2, 3], collectable_pdict)
351+
stream = Stream.into([1, 2, 3], %PDict{})
333352

334353
assert is_lazy(stream)
335354
assert Enum.take(stream, 1) == [1]
@@ -561,7 +580,7 @@ defmodule StreamTest do
561580
end
562581

563582
test "zip/2 closes on inner error" do
564-
stream = Stream.into([1, 2, 3], collectable_pdict)
583+
stream = Stream.into([1, 2, 3], %PDict{})
565584
stream = Stream.zip(stream, Stream.map([:a, :b, :c], fn _ -> throw(:error) end))
566585

567586
Process.put(:stream_done, false)
@@ -570,7 +589,7 @@ defmodule StreamTest do
570589
end
571590

572591
test "zip/2 closes on outer error" do
573-
stream = Stream.into([1, 2, 3], collectable_pdict)
592+
stream = Stream.into([1, 2, 3], %PDict{})
574593
|> Stream.zip([:a, :b, :c])
575594
|> Stream.map(fn _ -> throw(:error) end)
576595

@@ -592,14 +611,6 @@ defmodule StreamTest do
592611
match?(%Stream{}, stream) or is_function(stream, 2)
593612
end
594613

595-
defp collectable_pdict do
596-
fn
597-
_, {:cont, x} -> Process.put(:stream_cont, [x|Process.get(:stream_cont)])
598-
_, :done -> Process.put(:stream_done, true)
599-
_, :halt -> Process.put(:stream_halt, true)
600-
end
601-
end
602-
603614
defp inbox_stream({:suspend, acc}, f) do
604615
{:suspended, acc, &inbox_stream(&1, f)}
605616
end

0 commit comments

Comments
 (0)