summaryrefslogtreecommitdiff
path: root/lib/elixir
diff options
context:
space:
mode:
Diffstat (limited to 'lib/elixir')
-rw-r--r--lib/elixir/lib/enum.ex45
-rw-r--r--lib/elixir/lib/stream.ex6
-rw-r--r--lib/elixir/test/elixir/enum_test.exs119
-rw-r--r--lib/elixir/test/elixir/stream_test.exs2
4 files changed, 63 insertions, 109 deletions
diff --git a/lib/elixir/lib/enum.ex b/lib/elixir/lib/enum.ex
index 7cc751506..32a46d4fe 100644
--- a/lib/elixir/lib/enum.ex
+++ b/lib/elixir/lib/enum.ex
@@ -1647,13 +1647,9 @@ defmodule Enum do
Raises `Enum.EmptyError` if `enumerable` is empty.
- Notice that you need to explicitly call `:random.seed/1` and
- set a seed value for the random algorithm. Otherwise, the
- default seed will be set which will always return the same
- result. For example, one could do the following to set a seed
- dynamically:
-
- :random.seed(:os.timestamp)
+ This function uses Erlang's `:rand` module to calculate
+ the random value. Check its documentation for setting a
+ different random algorithm or a different seed.
The implementation is based on the
[reservoir sampling](https://en.wikipedia.org/wiki/Reservoir_sampling#Relation_to_Fisher-Yates_shuffle)
@@ -1663,10 +1659,12 @@ defmodule Enum do
## Examples
- iex> Enum.random([1, 2, 3])
- 1
+ # Although not necessary, let's seed the random algorithm
+ iex> :rand.seed(:exsplus, {1, 2, 3})
iex> Enum.random([1, 2, 3])
2
+ iex> Enum.random([1, 2, 3])
+ 1
"""
@spec random(t) :: element | no_return
@@ -1714,29 +1712,24 @@ defmodule Enum do
@doc """
Returns a list with the elements of `enumerable` shuffled.
- Notice that you need to explicitly call `:random.seed/1` and
- set a seed value for the random algorithm. Otherwise, the
- default seed will be set which will always return the same
- result. For example, one could do the following to set a seed
- dynamically:
-
- :random.seed(:os.timestamp)
-
- To see what happens if you don't do this, shuffle the same list
- in two separate IEx sessions. The results will be the same.
+ This function uses Erlang's `:rand` module to calculate
+ the random value. Check its documentation for setting a
+ different random algorithm or a different seed.
## Examples
+ # Although not necessary, let's seed the random algorithm
+ iex> :rand.seed(:exsplus, {1, 2, 3})
iex> Enum.shuffle([1, 2, 3])
- [3, 2, 1]
+ [2, 1, 3]
iex> Enum.shuffle([1, 2, 3])
- [3, 1, 2]
+ [2, 3, 1]
"""
@spec shuffle(t) :: list
def shuffle(enumerable) do
randomized = reduce(enumerable, [], fn x, acc ->
- [{:random.uniform, x}|acc]
+ [{:rand.uniform, x}|acc]
end)
unwrap(:lists.keysort(1, randomized), [])
end
@@ -2148,10 +2141,12 @@ defmodule Enum do
## Examples
+ # Although not necessary, let's seed the random algorithm
+ iex> :rand.seed(:exsplus, {1, 2, 3})
iex> Enum.take_random(1..10, 2)
- [1, 5]
+ [5, 8]
iex> Enum.take_random(?a..?z, 5)
- 'tfesm'
+ 'fhjni'
"""
@spec take_random(t, integer) :: list
@@ -2386,7 +2381,7 @@ defmodule Enum do
defp enum_to_string(entry), do: String.Chars.to_string(entry)
defp random_index(n) do
- :random.uniform(n + 1) - 1
+ :rand.uniform(n + 1) - 1
end
## Implementations
diff --git a/lib/elixir/lib/stream.ex b/lib/elixir/lib/stream.ex
index ac9efcd87..7ccfa7ab5 100644
--- a/lib/elixir/lib/stream.ex
+++ b/lib/elixir/lib/stream.ex
@@ -1023,8 +1023,10 @@ defmodule Stream do
## Examples
- iex> Stream.repeatedly(&:random.uniform/0) |> Enum.take(3)
- [0.4435846174457203, 0.7230402056221108, 0.94581636451987]
+ # Although not necessary, let's seed the random algorithm
+ iex> :rand.seed(:exsplus, {1, 2, 3})
+ iex> Stream.repeatedly(&:rand.uniform/0) |> Enum.take(3)
+ [0.40502929729990744, 0.45336720247823126, 0.04094511692041057]
"""
@spec repeatedly((() -> element)) :: Enumerable.t
diff --git a/lib/elixir/test/elixir/enum_test.exs b/lib/elixir/test/elixir/enum_test.exs
index f608801ad..1cc2bafba 100644
--- a/lib/elixir/test/elixir/enum_test.exs
+++ b/lib/elixir/test/elixir/enum_test.exs
@@ -304,16 +304,16 @@ defmodule EnumTest.List do
# set a fixed seed so the test can be deterministic
# please note the order of following assertions is important
seed1 = {1406, 407414, 139258}
- seed2 = {1406, 421106, 567597}
- :random.seed(seed1)
+ seed2 = {1306, 421106, 567597}
+ :rand.seed(:exsplus, seed1)
+ assert Enum.random([1, 2]) == 1
+ assert Enum.random([1, 2, 3]) == 1
+ assert Enum.random([1, 2, 3, 4]) == 2
+ assert Enum.random([1, 2, 3, 4, 5]) == 4
+ :rand.seed(:exsplus, seed2)
assert Enum.random([1, 2]) == 2
assert Enum.random([1, 2, 3]) == 2
- assert Enum.random([1, 2, 3, 4]) == 4
- assert Enum.random([1, 2, 3, 4, 5]) == 1
- :random.seed(seed2)
- assert Enum.random([1, 2]) == 1
- assert Enum.random([1, 2, 3]) == 3
- assert Enum.random([1, 2, 3, 4]) == 1
+ assert Enum.random([1, 2, 3, 4]) == 3
assert Enum.random([1, 2, 3, 4, 5]) == 5
end
@@ -330,25 +330,21 @@ defmodule EnumTest.List do
# please note the order of following assertions is important
seed1 = {1406, 407414, 139258}
seed2 = {1406, 421106, 567597}
- :random.seed(seed1)
- assert Enum.take_random([1, 2, 3, 4, 5], 1) == [2]
- assert Enum.take_random([1, 2, 3, 4, 5], 2) == [4, 1]
- assert Enum.take_random([1, 2, 3, 4, 5], 3) == [1, 3, 5]
- assert Enum.take_random([1, 2, 3, 4, 5], 4) == [3, 5, 1, 2]
- assert Enum.take_random([1, 2, 3, 4, 5], 5) == [1, 2, 5, 4, 3]
- assert Enum.take_random([1, 2, 3, 4, 5], 6) == [2, 4, 5, 3, 1]
- :random.seed(seed2)
- assert Enum.take_random([1, 2, 3, 4, 5], 1) == [1]
- assert Enum.take_random([1, 2, 3, 4, 5], 2) == [1, 5]
- assert Enum.take_random([1, 2, 3, 4, 5], 3) == [5, 1, 3]
- assert Enum.take_random([1, 2, 3, 4, 5], 4) == [4, 5, 2, 1]
- assert Enum.take_random([1, 2, 3, 4, 5], 5) == [4, 3, 1, 5, 2]
- assert Enum.take_random([1, 2, 3, 4, 5], 6) == [5, 2, 1, 4, 3]
+ :rand.seed(:exsplus, seed1)
+ assert Enum.take_random([1, 2, 3], 1) == [1]
+ assert Enum.take_random([1, 2, 3], 2) == [1, 3]
+ assert Enum.take_random([1, 2, 3], 3) == [2, 1, 3]
+ assert Enum.take_random([1, 2, 3], 4) == [3, 1, 2]
+ :rand.seed(:exsplus, seed2)
+ assert Enum.take_random([1, 2, 3], 1) == [3]
+ assert Enum.take_random([1, 2, 3], 2) == [1, 2]
+ assert Enum.take_random([1, 2, 3], 3) == [1, 2, 3]
+ assert Enum.take_random([1, 2, 3], 4) == [1, 2, 3]
# assert that every item in the sample comes from the input list
list = for _<-1..100, do: make_ref
for x <- Enum.take_random(list, 50) do
- assert Enum.find(list, &(&1 == x))
+ assert x in list
end
end
@@ -362,8 +358,8 @@ defmodule EnumTest.List do
test "shuffle" do
# set a fixed seed so the test can be deterministic
- :random.seed(1374, 347975, 449264)
- assert Enum.shuffle([1, 2, 3, 4, 5]) == [2, 4, 1, 5, 3]
+ :rand.seed(:exsplus, {1374, 347975, 449264})
+ assert Enum.shuffle([1, 2, 3, 4, 5]) == [2, 1, 3, 5, 4]
end
test "sort" do
@@ -935,25 +931,13 @@ defmodule EnumTest.Range do
# set a fixed seed so the test can be deterministic
# please note the order of following assertions is important
seed1 = {1406, 407414, 139258}
- seed2 = {1406, 421106, 567597}
- :random.seed(seed1)
+ seed2 = {1306, 421106, 567597}
+ :rand.seed(:exsplus, seed1)
+ assert Enum.random(1..2) == 1
+ assert Enum.random(1..3) == 1
+ :rand.seed(:exsplus, seed2)
assert Enum.random(1..2) == 2
assert Enum.random(1..3) == 2
- assert Enum.random(1..4) == 4
- assert Enum.random(1..5) == 1
- :random.seed(seed1)
- assert Enum.random(?a..?z) == ?i
- :random.seed(seed1)
- assert Enum.random(?0..?9) == ?8
- :random.seed(seed2)
- assert Enum.random(1..2) == 1
- assert Enum.random(1..3) == 3
- assert Enum.random(1..4) == 1
- assert Enum.random(1..5) == 5
- :random.seed(seed2)
- assert Enum.random(?a..?z) == ?a
- :random.seed(seed2)
- assert Enum.random(?0..?9) == ?0
end
test "take random" do
@@ -967,43 +951,16 @@ defmodule EnumTest.Range do
# please note the order of following assertions is important
seed1 = {1406, 407414, 139258}
seed2 = {1406, 421106, 567597}
- :random.seed(seed1)
- assert Enum.take_random(1..5, 1) == [2]
- assert Enum.take_random(1..5, 2) == [4, 1]
- assert Enum.take_random(1..5, 3) == [1, 3, 5]
- assert Enum.take_random(1..5, 4) == [3, 5, 1, 2]
- assert Enum.take_random(1..5, 5) == [1, 2, 5, 4, 3]
- assert Enum.take_random(1..5, 6) == [2, 4, 5, 3, 1]
- :random.seed(seed2)
- assert Enum.take_random(1..5, 1) == [1]
- assert Enum.take_random(1..5, 2) == [1, 5]
- assert Enum.take_random(1..5, 3) == [5, 1, 3]
- assert Enum.take_random(1..5, 4) == [4, 5, 2, 1]
- assert Enum.take_random(1..5, 5) == [4, 3, 1, 5, 2]
- assert Enum.take_random(1..5, 6) == [5, 2, 1, 4, 3]
-
- :random.seed(seed1)
- assert Enum.take_random(1..200, 130) == [107, 168, 172, 88, 98, 89, 64, 104, 161,
- 28, 128, 125, 30, 182, 194, 140, 198, 113, 191, 69, 126, 37, 115, 147, 193, 152,
- 154, 145, 127, 99, 148, 52, 17, 63, 59, 54, 38, 80, 100, 188, 122, 19, 41, 108,
- 26, 81, 10, 158, 195, 60, 95, 24, 117, 163, 141, 62, 116, 176, 156, 31, 73, 120,
- 55, 76, 44, 174, 110, 25, 136, 166, 149, 83, 106, 159, 46, 138, 157, 187, 93, 131,
- 180, 109, 162, 67, 22, 5, 170, 18, 143, 177, 146, 153, 34, 167, 137, 160, 175, 16,
- 74, 1, 51, 134, 47, 35, 85, 75, 179, 61, 130, 151, 118, 129, 164, 42, 86, 48, 186,
- 8, 192, 20, 90, 150, 178, 39, 92, 171, 56, 2, 200, 155]
-
- :random.seed(seed1)
- assert Enum.take_random(?a..?z, 1) == 'i'
- assert Enum.take_random(?a..?z, 2) == 'cm'
- assert Enum.take_random(?a..?z, 3) == 'alp'
- assert Enum.take_random(?a..?z, 4) == 'tzmd'
- assert Enum.take_random(?a..?z, 5) == 'cuxvb'
- :random.seed(seed2)
- assert Enum.take_random(?a..?z, 1) == 'a'
- assert Enum.take_random(?a..?z, 2) == 'wk'
- assert Enum.take_random(?a..?z, 3) == 'ayj'
- assert Enum.take_random(?a..?z, 4) == 'rbcm'
- assert Enum.take_random(?a..?z, 5) == 'rhzju'
+ :rand.seed(:exsplus, seed1)
+ assert Enum.take_random(1..3, 1) == [1]
+ assert Enum.take_random(1..3, 2) == [1, 3]
+ assert Enum.take_random(1..3, 3) == [2, 1, 3]
+ assert Enum.take_random(1..3, 4) == [3, 1, 2]
+ :rand.seed(:exsplus, seed2)
+ assert Enum.take_random(1..3, 1) == [3]
+ assert Enum.take_random(1..3, 2) == [1, 2]
+ assert Enum.take_random(1..3, 3) == [1, 2, 3]
+ assert Enum.take_random(1..3, 4) == [1, 2, 3]
end
test "scan" do
@@ -1013,8 +970,8 @@ defmodule EnumTest.Range do
test "shuffle" do
# set a fixed seed so the test can be deterministic
- :random.seed(1374, 347975, 449264)
- assert Enum.shuffle(1..5) == [2, 4, 1, 5, 3]
+ :rand.seed(:exsplus, {1374, 347975, 449264})
+ assert Enum.shuffle(1..5) == [2, 1, 3, 5, 4]
end
test "slice" do
diff --git a/lib/elixir/test/elixir/stream_test.exs b/lib/elixir/test/elixir/stream_test.exs
index 361c788d3..cb2094c6a 100644
--- a/lib/elixir/test/elixir/stream_test.exs
+++ b/lib/elixir/test/elixir/stream_test.exs
@@ -478,7 +478,7 @@ defmodule StreamTest do
test "repeatedly/1" do
stream = Stream.repeatedly(fn -> 1 end)
assert Enum.take(stream, 5) == [1, 1, 1, 1, 1]
- stream = Stream.repeatedly(&:random.uniform/0)
+ stream = Stream.repeatedly(&:rand.uniform/0)
[r1, r2] = Enum.take(stream, 2)
assert r1 != r2
end