何が嫌か
Elixirで例えばHttPoisonやらJasonやらを使ってサクッとスクリプトを書いて実行したいのにサクッとならない。
mapをjsonにエンコードする以下のようなスクリプトを書いたとして
%{foo: "bar"}
|> Jason.encode!
|> IO.puts
これを普通にelixir
コマンドで実行しようとすると
$ elixir foo.exs
** (UndefinedFunctionError) function Jason.encode!/1 is undefined (module Jason is not available)
Jason.encode!(%{foo: "bar"})
foo.exs:2: (file)
(elixir) lib/code.ex:767: Code.require_file/2
怒られる。世知辛い世の中。
当然といえば当然で、プロジェクトマネージャたるMix
を使うとパッケージはグローバルにインストールされることはない。というかできない。
これはこれでプロジェクトごとにパッケージがクリーンに保たれるので、某pythonみたいにvirtualenvなんてものを考える必要はない。
その点でelixirおよびmixは素晴らしいと言えるのだが、時々こういう感じで困る。
結局どうしたか
escriptにdependencyを全部ぶち込んでElixir scriptを動的に読み込んで実行することでだいたい解決できた。
以下にerun
として公開している(驚くほど実装の中身がない)。
s417-lama/erun
Jasonをdepsに指定すればさっきの例は以下のようにちゃんと実行される。
$ erun foo.exs
{"foo":"bar"}
使い方
(1) cloneする
git clone git@github.com:s417-lama/erun.git
(2) mix.exs
をいじって好きなdepsを指定する
defp deps do
[
{:super_package, "~> 1.0"},
...
]
end
(3) deps.get
mix deps.get
(4) コンパイルしてインストール
mix escript.install
(5) 使ってみる
$ erun -e "IO.puts :hello"
hello
あと、地味にErun.args/0
を呼ぶと引数を取得できる。
$ erun -e "IO.inspect Erun.args" foo bar 1
["foo", "bar", "1"]
何ができないか
iex
でグローバルなパッケージを読み込みたいが、erun
ではできない(スクリプト限定)。
なにか良いアイデアはないでしょうか...?