Sunday, April 21, 2019

Chapter 1 Elixir

Run the command mix new counter and in the folder counter\lib, edit counter.ex.
defmodule Counter.Core do

  def inc(value) do
    value + 1
  end
end

defmodule Clock do
  def start(f) do
    run(f, 0)
  end

  def run(endless, count) do
    endless.(count)
    new_count = Counter.Core.inc(count)
    :timer.sleep(1000)
    run(endless, new_count)
  end
end


Chapter 2 Elixir

defmodule Counter.Core do

  def inc(value) do
    value + 1
  end
end

defmodule Counter.Server do
  def run(count) do
    new_count = listen(count)
    run(new_count)
  end

  def listen(count) do
    receive do
      {:tick, _pid} ->
        Counter.Core.inc(count)
      {:state, pid} ->
        send(pid, {:count, count})
        count
    end
  end
end

defmodule Counter do
  def start(initial_count) do
    spawn( fn() -> Counter.Server.run(initial_count) end)
  end
  def tick(pid) do
    send pid, {:tick, self()}
  end
  def state(pid) do
    send pid, {:state, self()}
    receive do
      {:count, value} -> value
    end
  end
end


Chapter 3 Elixir

Add test file counter_test.exs to the test folder
defmodule CounterTest do
  use ExUnit.Case
  test "inc increments an integer value" do
    assert Counter.Core.inc(1) == 2
  end
end
Add test file counter_api_test.exs to the test folder
defmodule CounterApiTest do
  use ExUnit.Case
  test "use counter through API" do
    pid = Counter.start(0)
    assert Counter.state(pid) == 0
  
    Counter.tick(pid)
    Counter.tick(pid)
  
    count = Counter.state(pid)
    assert count == 2
  end
end


Chapter 4 Elixir

Create folder simple_elixir and in it create file hello.exs
IO.puts "hello world"


Chapter 5 Elixir

run mix new pmap and edit pmap\lib\pmap.ex
defmodule Parallel do
  def pmap(collection, func) do
    collection 
 |> Enum.map(&(Task.async(fn -> func.(&1) 
 end)))
 |> Enum.map(&Task.await/1)
 
  end
end


Chapter 6 Elixir

Investigate functions using h(), the help function.

Chapter 7 Elixir

Investigate concurrency. Run mix new add_example and edit add_example/lib/add_example.ex
defmodule Add_Example do
  def add(a, b) do
    IO.puts(a + b)
  end
end
Run iex -S mix then enter the following two commands at the prompt to first make a blocking call then an asynchronous call.

Modify the code to process the response from the asynchronous call.
defmodule Add_Example do
  def listen do
    receive do
      {:ok, "hello"} -> IO.puts("World")
    end
    listen
  end
end


Tuples and Lists

iex(15)> coins = [{"penny", 1}, {"nickel", 5}]
[{"penny", 1}, {"nickel", 5}]

iex(16)> coins = coins ++ [{"dime", 10}]
[{"penny", 1}, {"nickel", 5}, {"dime", 10}]

iex(17)> coins = coins ++ [{"quarter", 25}]
[{"penny", 1}, {"nickel", 5}, {"dime", 10}, {"quarter", 25}]

iex(18)> coins = [penny: 1, nickel: 5, dime: 10, quarter: 25]
[penny: 1, nickel: 5, dime: 10, quarter: 25]
 
iex(19)> Keyword.get(change, :dime)
10
 
iex(20)> change[:nickel]
5
 
iex(21)> change = [penny: 1] ++ [nickel: 5] ++ [dime: 10]
[penny: 1, nickel: 5, dime: 10]
 
iex(22)> pocket_change = [{"penny", 1}] ++ [{"nickel", 5}] ++ [{"dime", 10}]
[{"penny", 1}, {"nickel", 5}, {"dime", 10}]
 
iex(23)> {name, age} = {"Bob", 25}
{"Bob", 25}
 
iex(24)> bob = {name, age}
{"Bob", 25}

iex(25)> {date, time} = :calendar.local_time
{{2019, 4, 30}, {22, 22, 24}}

iex(26)> {_, {hours, minutes, _}} = :calendar.local_time
{{2019, 4, 30}, {22, 28, 6}}

iex(27)> [head | tail] = [1, 2, 3, 4]
[1, 2, 3, 4]

iex(28)> head
1

iex(29)> tail
[2, 3, 4]

iex(30)> [head1 | [head2 | tail]] = [1, 2, 3, 4]
[1, 2, 3, 4]

iex(31)> head1
1

iex(32)> head2
2

iex(33)> 


Simple Functions

defmodule Splitter do
  def comma_split(str_quote) do
    str_quote |> String.split(",")
  end
  
  def letter_split(str_quote) do
    str_quote |> String.codepoints
  end
end


Overloaded Functions

defmodule Geo do 
  def how_big({:circle, radius}) do 
    radius * radius * 3.14 
  end
  
  def how_big({:rectangle, {l, w}}) do 
    l * w 
  end
end

iex(1)> Geo.how_big({:circle, 5})
78.5
iex(2)> Geo.how_big({:rectangle, {4, 5}})
20
iex(3)>


Equality

To avoid reassigning values to the variable, I move the variable to the RHS of the expression.
iex(1)> k9 = %{dog1: "dog", fox1: "fox"}
%{dog1: "dog", fox1: "fox"}

iex(2)> %{dog1: "dog", fox1: "fox"} = k9
%{dog1: "dog", fox1: "fox"}

iex(3)> %{dog1: "dog", fox1: "cat"} = k9
** (MatchError) no match of right hand side value: %{dog1: "dog", fox1: "fox"}

iex(4)>


Recursive Functions

defmodule Lists do
  def map([], _func), do: []
  def map([h | t], func), do: [func.(h) | map(t, func)]
end

iex(1)> Lists.map([], fn x -> 3 * x end)
[]
iex(2)> Lists.map([2,4,6], fn x -> 3 * x end)
[6, 12, 18]