-
Notifications
You must be signed in to change notification settings - Fork 0
/
sequence.exs
85 lines (64 loc) · 1.89 KB
/
sequence.exs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
defmodule Sequence do
@doc """
An performant implentation of fibonacci numbers
[ 36, 37, 38, 39, 39, 39, 39, 39 ] |> Sequence.map( Sequence.fib(&1) )
[ 36, 37, 38, 39, 39, 39, 39, 39 ] |> Sequence.pmap( Sequence.fib(&1) )
iex> Sequence.fib(10)
55
"""
def fib(number), do: fib(0, 1, number)
defp fib(_, b, 1), do: b
defp fib(a, b, number), do: fib(b, a + b, number - 1)
@doc """
Maps a collection to another collection applying the given function to each element.
iex> Sequence.map( [ 1, 2, 3 ], &1 * &1)
[ 1, 4, 9 ]
iex> Sequence.map( [], &1 * &1)
[ ]
"""
def map([], _fun), do: []
def map([h|t], fun), do: [ fun.(h) | map(t, fun) ]
@doc """
Maps a collection to another collection applying the given function to each element.
iex> Sequence.pmap( [ 1, 2, 3 ], &1 * &1)
[ 1, 4, 9 ]
iex> Sequence.pmap( [], &1 * &1)
[ ]
"""
def pmap(collection, fun) do
collection |> spawn_children(fun) |> collect_results
end
"""
Spawns children for each element in the collection, returns a list of pids
"""
defp spawn_children(collection, fun) do
collection |> map( spawn_child(&1, fun) )
end
defp spawn_child(elem, fun) do
spawn Sequence, :child_execution, [ self, elem, fun ]
end
defp collect_results(pids) do
pids |> map(result_for_pid(&1))
end
defp result_for_pid(pid) do
receive do
{ ^pid, value } -> value
end
end
def child_execution(parent_pid, elem, fun) do
parent_pid <- { self, fun.(elem) }
end
end
ExUnit.start
defmodule SequenceTest do
use ExUnit.Case
doctest Sequence
test 'a child executes a function and sends the result back' do
#child_pid == self
Sequence.child_execution( self, 3, &1 * &1 )
assert_receive { self, 9 }
#with a real child
child = spawn Sequence, :child_execution, [ self, 4, &1 * &1 ]
assert_receive { child, 16 }
end
end