動かざることバグの如し

近づきたいよ 君の理想に

Elixir で配列をループしたいならEnum.each

Elixirで頻出する Enum.each/2 だが、書き方色々あって全然見れなかったのでメモ。

基本形

Enum.each(["one", "two", "three"], fn(x) -> IO.inspect(x) 
end)
# 出力
# "one"
# "two"
# "three"

省略記法を使う

Elixirでは無名関数を&を使って省略記法で書ける

これを使うと、 fn() -> end&() 、もっというと fn(x) -> fn2(x) end&fn2/1 と省略できるので、

Enum.each(["one", "two", "three"], &IO.inspect/1)

と書くことができる。

パイプライン演算子を使う

さらにパイプライン演算子を使うと

["one", "two", "three"] |> Enum.each(&IO.inspect/1)

と書くこともできる。

慣れるまで大変だけど数こなすしかないね。。。

Elixir マップの値を更新する方法3選

環境

  • Elixir 1.x

やりたいこと

例えば、以下のようなMapがあったとする。

user = %{name: "Taro", gender: "man", city: "Tokyo"}

ここのcityのTokyoの値を変更したり、あたらしくidのキーを追加したい。

存在するキーを更新する場合

パイプ文字を使った new_map = %{ old_map | key => value, ...} を使う。

new_user = %{user| city: "sendai"}
# => %{city: "sendai", gender: "man", name: "Taro"}

引数に続けば複数一括更新できる。

new_user = %{user | city: "sendai", name: "Ziro"}

キーが存在しなかった場合エラーになる。

iex(10)> new_user = %{user| id: 123}                         
** (KeyError) key :id not found in: %{city: "Tokyo", gender: "man", name: "Taro"}
    (stdlib) :maps.update(:id, 123, %{city: "Tokyo", gender: "man", name: "Taro"})
    (stdlib) erl_eval.erl:255: anonymous fn/2 in :erl_eval.expr/5
    (stdlib) lists.erl:1263: :lists.foldl/3

キーが存在しない場合

Map.put_new/3 を使う必要がある。

new_user = Map.put user, :id, 123
# => %{city: "Tokyo", gender: "man", id: 123, name: "Taro"}

こっちはキーが存在していても更新される。

new_user = Map.put user, :city, "sendai"
# => %{city: "sendai", gender: "man", name: "Taro"}

このように書くこともできる。

user |> Map.put(:city, "sendai")

Map.merge/2 も利用可能

Map.merge(user, %{city: "sendai"} )

じゃあキーの有無考えなくていい Map.put 全部使えばいいじゃんって話だが、本来存在しなきゃいけないときに気づけない場合もある。

ちゃんと使いどきを考えよう

ElixirでTupleをListに変換する

久々にカテゴリ増やした気がする(怠慢

環境

  • Elixir 1.6

コード

Elixirの教科書本ことプログラミングElixirの演習問題でわからなかったのでメモ

プログラミングElixir 第2版

プログラミングElixir 第2版

Tuple.to_list({1234, 5678})
# => [1234, 5678]

よって演習問題の答えは以下のようになる

pair_tuple_to_list = fn(a) -> Tuple.to_list(a) end
pair_tuple_to_list.( {1234, 5678} )

Ruby irbするとreadlineエラーになる件

環境

結論

readline入れろ

brew install readline

が、残念ながらこれだけだとライブラリのパスがruby-buildから見えないので、

RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)" rbenv install 3.0.0

する必要がある。

~/.zshrcとかに

export RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)"

しておけばよい

問題

rbenv でRubyをインストールしたものの、 pryとかirbが以下のようなエラーが表示され、起動できない。

$ pry
Sorry, you can't use Pry without Readline or a compatible library.
Possible solutions:
 * Rebuild Ruby with Readline support using `--with-readline`
 * Use the rb-readline gem, which is a pure-Ruby port of Readline
 * Use the pry-coolline gem, a pure-ruby alternative to Readline

インストール時になかったらエラーになれよ、、、と思うがこれで解決した。やったね