プログラミング Elixir 確認メモ (1)
とりあえずメモを控え。あと markdown の preview をコピペとか色々微妙 (こら
ドキュメント
続
ListsAndRecursion-5
とりあえず Enum.all? から。使用例として挙げられているのが以下でした。
> Enum.all?(list, &(&1 < 4))
false
list は以下な定義です。
> list = Enum.to_list 1..5
[1, 2, 3, 4, 5]
うーん、、、if 使うと簡単なんですが他の方法ないのかしら。
defmodule EnumExcercise do
def all?([], _func) do
true
end
def all?([head|tail], func) do
if func.(head) do
all?(tail, func)
else
false
end
end
end
こうかしら。
defmodule EnumExcercise do
def all?([], _func) do
true
end
def all?([head|tail], func) do
_all?(func.(head), tail, func)
end
def _all?(false, _list, _func) do
false
end
def _all?(true, list, func) do
all?(list, func)
end
end
次、Enum.each ですがこれどこで例示されているのやら。と思ったら単純に list に関数を適用すれば良いのかしら。
def each([], _func), do: []
def each([head|tail], func) do
[func.(head)|each(tail, func)]
end
次、Enum.filter て何かしら。
> Enum.filster([1, 2, 3, 4, 5], &(&1 > 2))
[3, 4, 5]
これも簡単。
def filter([], _func), do: []
def filter([head|tail], func) do
if func.(head) do
[head|filter(tail, func)]
else
filter(tail, func)
end
end
リスト走査て SICP 以来で懐しい。次は split とのこと。例示されているのが以下。
> Enum.split([1, 2, 3, 4, 5], 3)
{[1, 2, 3], [4, 5]}
tuple になってるのか。どうやるんだろ。
tuple を戻す
引数ごとでリストを分割
こんなことができるのか。
[first, second, third|tail] = list
でもこれ、要素数が合わないと駄目みたい。こまったなと言いつつ探してみたら以下なナニが出てきた。
def split(list, num) do
_split([], list, num)
end
defp _split(taken, remaining, 0) do
{ taken, remaining }
end
defp _split(taken, [remaining_head | remaining_tail], num) do
_split(taken ++ [remaining_head], remaining_tail, num - 1)
end
ええとこれ、num が 0 になったら終わるよね。てことは
defp _split(taken, [], 0) do
end
なソレがあれば良いのかな。で、どハマッた挙句に以下がでっちあがりました。
def split(list, num) do
_split([], [], list, num, num)
end
# result が空でリスト終了
defp _split([], splited, [], _count, _num) do
{splited}
end
# リスト終了
defp _split(result, splited, [], _count, _num) do
List.to_tuple(result ++ [splited])
end
# 最初
defp _split([], [], [remaining_head|remaining_tail], count, num) do
_split([], [remaining_head], remaining_tail, count-1, num)
end
# result が空で count が 0
defp _split([], splited, [remaining_head|remaining_tail], 0, num) do
_split([splited], [], [remaining_head|remaining_tail], num, num)
end
# result が空
defp _split([], splited, [remaining_head|remaining_tail], count, num) do
_split([], splited ++ [remaining_head], remaining_tail, count - 1, num)
end
# count が 0
defp _split(result, splited, [remaining_head|remaining_tail], 0, num) do
_split(result ++ [splited], [remaining_head], remaining_tail, num, num)
end
defp _split(result, splited, [remaining_head|remaining_tail], count, num) do
_split(result, splited ++ [remaining_head], remaining_tail, count - 1, num)
end
List.to_tuple 使わざるを得ず。。。
つづき
ModulesAndFundtions-7
浮動小数点数を二つの 10 進数文字列に変換
Erlang な模様。どうやって探すのかと。以下?
これで良いのかしら
> :erlang.float_to_list(3.14, [:short])
~c"3.14"
ファイル名の拡張子を取り出す
これは Elixir の extname で良いのかしら。
> Path.extname("dave/test.exs")
".exs"
プロセスの現在の作業ディレクトリを戻す
Elixir の、とのこと。探し方がいまひとつ微妙。
> File.cwd
{:ok, "/root"}
JSON 文字列を Elixir データ構造に変換
これは見つけるだけで良いとのこと。poison てのがある、とのこと。
オペレーティングシステムのシェルでコマンドを実行
これ、System.cmd なのかしら。と思ったらなんか叱られた。System.shell な模様。
> System.shell("echo hello")
{"hello\n", 0}
ListsAndRecursion-1
List/Scheme 風で考え易い。実装以下。
defmodule MyList do
def mapsum([], _func) do
0
end
def mapsum([head|tail], func) do
func.(head) + mapsum(tail, func)
end
end
でコンパイルして実行。
> MyList.mapsum([1, 2, 3], &(&1*&1))
14
ListsAndRecursion-2
リストの要素の最大値を返す max(list) を、とのこと。最大値か。。つうか Enum.max てのがあるようですが。。。
defmodule MyList do
def max([head|tail]) do
_max(head, tail)
end
def _max(max_value, []) do
max_value
end
def _max(max_value, [head|tail]) do
_max(if(head > max_value, do: head, else: max_value), tail)
end
end
どうやるのかしらと思ってたら if は関数とのこと。ややトリッキー、ってのはこのあたりなのかしら。
ListsAndRecursion-3
微妙なのがでっちあがりました。
defmodule MyList do
def ceasar([], _n) do
[]
end
def ceasar([head|tail], n) do
[if(head+n > 122, do: 96 + (head+n-122), else: head+n)|ceasar(tail, n)]
end
end
絶対これ微妙。出力はあってるみたいですが。。。
> MyList.ceasar('ryvkve', 13)
~c"elixir"
ListsAndRecursion-4
これで良いのかしら。
defmodule MyList do
def span(to, to), do: [to]
def span(from, to) do
[from | span(from+1, to)]
end
end
一応大丈夫、なのかどうか。
> MyList.span(1, 5)
[1, 2, 3, 4, 5]
つうか、パタンマッチ強力ですね。
chapter.12 までは
iex で云々します。あと vscode で C-j が改行に割り当てられてるの何とかせねば。
キーバインド削除で
何とかなりました。
練習問題1
> list_concat = fn l1, l2 -> l1 ++ l2 end
> list_concat.([:a, :b], [:c, :d])
[:a, :b, :c, :d]
> sum = fn a, b, c -> a + b + c end
> sum.(1, 2, 3)
6
> pair_tuple_to_list = fn {p1, p2} -> [p1, p2] end
> > pair_tuple_to_list.({1234, 5678})
[1234, 5678]
練習問題2
> functions2 = fn
...> {0, 0, _} -> "FizzBuzz"
...> {0, _, _} -> "Fizz"
...> {_, 0, _} -> "Buzz"
...> {_, _, x} -> "#{x}"
...> end
> functions2.({0, 0, 1})
"FizzBuzz"
> functions2.({0, 1, 1})
"Fizz"
> functions2.({1, 0, 1})
"Buzz"
> functions2.({1, 1, 1})
"1"
練習問題3
> functions3 = fn n -> functions2.({rem(n, 3), rem(n, 5), n}) end
> functions3.(10)
"Buzz"
> functions3.(11)
"11"
> functions3.(12)
"Fizz"
> functions3.(13)
"13"
> functions3.(14)
"14"
> functions3.(15)
"FizzBuzz"
> functions3.(16)
"16"
練習問題4
こうだった
prefix = fn first -> (fn second -> "#{first} #{second}" end) end
文字列の扱いがアレ。
練習問題5
> Enum.map [1, 2, 3, 4], fn x -> x + 2 end
[3, 4, 5, 6]
> Enum.map [1, 2, 3, 4], &(&1 + 2)
[3, 4, 5, 6]
あるいは
> Enum.map [1, 2, 3, 4], fn x -> IO.inspect x end
1
2
3
4
[1, 2, 3, 4]
> Enum.map [1, 2, 3, 4], &(IO.inspect &1)
1
2
3
4
[1, 2, 3, 4]
モジュールのコンパイル (練習問題)
注意。mm ディレクトリに times.exs があるとすると
c "mm/times.exs"
でないと駄目。
再起
定義の順番が重要とのこと。
defmodule Factorial do
def of(0), do: 1
def of(n), do: n * of(n - 1)
end
ModulesAndFunctions-6
考え方としては?
range な引数はパタンマッチで取得できる?
def guess(actual, start..end) (別途確認
end が actual より大きいかどうか、を判定する手続きが必要?
大きければ end を 2 で割ったナニ
推測値? ってどうやって取得するのかと。。。ヘルパ関数でアレなのかな。
(actual が 273 の場合)
1 と 1000 の場合、推測値は真ん中
最初が色々大変だった
aquaskk 入れるの大変でした
homebrew 導入
brew install --cask aquaskk
再起動
keyboard - input sources から skk 追加
docker desksop とか vscode とか入れた
latest な elixir 向け Dockerfile 入手して起動
とりあえずカレントディレクトリとファイル共有。
$ docker run -it -v .:/root 5fa37d9ab3a2 bash
この記事が気に入ったらサポートをしてみませんか?