1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Elixir episode:1 リスト

1
Last updated at Posted at 2019-05-11

環境

sh
$ lsb_release -d
Description:    Ubuntu 18.04.2 LTS

$ elixir -v
Erlang/OTP 21 [erts-10.3.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Elixir 1.8.1 (compiled with Erlang/OTP 20)

はじめに

Elixir episode:0 実行ファイル のプロジェクトを使う。
いや、使わんでもいい。

Fg.List

touch lib/fg/list.ex

fg/lib/fg/list.ex
defmodule Fg.List do
  def cons(x, y), do: [x | y]

  def head([x | _y]), do: x

  def tail([_x | y]), do: y
end

$ iex -S mix

iex
iex(1)> alias Fg.List, as: L
Fg.List
iex(2)> list = L.cons(1, L.cons(2, L.cons(3, [])))
[1, 2, 3]
iex(3)> L.head(list)
1
iex(4)> L.tail(list)
[2, 3]
iex(5)> L.head([1])
1
iex(6)> L.tail([1])
[]

おっけー?

無名関数

$ iex

iex
iex(1)> first = fn (x, _y) -> x end
# Function<12.128620087/2 in :erl_eval.expr/5>
iex(2)> second = fn (_x, y) -> y end
# Function<12.128620087/2 in :erl_eval.expr/5>
iex(3)> first.(1, 2)
1
iex(4)> second.(1, 2)
2

カリー化

全ての関数を、1引数の関数で表現すること。

iex
iex(5)> first = fn x -> fn _y -> x end end
# Function<6.128620087/1 in :erl_eval.expr/5>
iex(6)> second = fn _x -> fn y -> y end end
# Function<6.128620087/1 in :erl_eval.expr/5>
iex(7)> first.(1).(2)
1
iex(8)> second.(1).(2)
2

なんの役に立つのか?実利的にはあまり役に立たない。
関数とは何か?と考える場合には役に立つ。
ざっくり言えば、関数の一般化である。

ラムダ算法

ラムダ算法の説明はしない。
以下はカリー化を施した関数によって、
関数のみでリスト(データ構造)を作れることを示している。

iex
iex(9)> cons = fn x -> fn y ->  
...(9)>   fn selector -> selector.(x).(y) end
...(9)> end end
# Function<6.128620087/1 in :erl_eval.expr/5>
iex(10)> head = fn list -> list.(first) end
# Function<6.128620087/1 in :erl_eval.expr/5>
iex(11)> tail = fn list -> list.(second) end
# Function<6.128620087/1 in :erl_eval.expr/5>
iex(12)> list = cons.(1).(2)   
# Function<6.128620087/1 in :erl_eval.expr/5>
iex(13)> head.(list)
1
iex(14)> tail.(list)
2
iex(15)> list = cons.(1).(cons.(2).(cons.(3).(nil)))
# Function<6.128620087/1 in :erl_eval.expr/5>
iex(16)> head.(list)
1
iex(17)> head.(tail.(list))
2
iex(18)> head.(tail.(tail.(list)))
3
iex(19)> tail.(tail.(tail.(list)))       
nil

Fg.List を書き換える

fg/lib/fg/list.ex
defmodule Fg.List do
  def cons(x, y) do
    fn selector when is_function(selector, 2) ->
      selector.(x, y)
    end
  end

  def head(list) when is_function(list, 1) do
    fn x, _y -> x end  # first selector
    |> list.()
  end

  def tail(list) when is_function(list, 1) do
    fn _x, y -> y end  # second selector
    |> list.()
  end
end

$ iex -S mix

iex
iex(1)> alias Fg.List, as: L
Fg.List
iex(2)> list = L.cons(1, L.cons(2, L.cons(3, nil)))
# Function<0.76478687/1 in Fg.List.cons/2>
iex(3)> L.head(list)
1
iex(4)> L.tail(list)
# Function<0.76478687/1 in Fg.List.cons/2>
iex(5)> L.tail(list) |> L.head()
2
iex(6)> L.tail(list) |> L.tail() |> L.head()
3
iex(7)> L.tail(list) |> L.tail() |> L.tail()
nil

また来てくれよなーノシ

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?