コマンドラインアプリケーションを作成することで


私は簡単なコマンドラインアプリケーションを書くことによってElixir
そして、基本的なElixirプロジェクトのセットアップを紹介します.
最近、私は魅了されましたElixir . それは岩のような基盤に建てられた素敵な小さな言語です.
だけでなく、そのルビーの一見見て目にかなり簡単ですが、使用可能な記事やツールを簡単に指示を歓迎し、インターフェイスを使用する直感的な構文.
最初から機能的な言語であったErlangの上で構築して、機能的な概念はElixirにセンターで、彼らがしばしばJVMまたはJavaScript Runtimeの上に構築される機能的言語で感覚を得るので、彼らは誤って置かれるか、後戻りのように感じません.
Pattern matching 宣言的なコードを書いて、入力から驚くべきことを除外する信じられないほどエレガントな方法です.Recursion がサポートされている.データはimmutable . そして、あなたが外部のサービスとの同時性とコミュニケーションを取り扱う同じ一貫した方法で、あなたは優雅に状態を取り扱いますactor model メッセージ渡し.弾力性のある、耐故障性システムを構築することは、Erlangprocesses and supervisor これはシステムの一部としてエラーを受け入れるという概念であり、プログラムの一部をシステム全体を下げることなく優雅に失敗させます.
エリクソンのコミュニティは素晴らしい仕事をしました:エディタのサポート、ツーリング、標準的なライブラリとサードパーティ製のパッケージを使用して簡単に始めるために喜びです.
エリキシル生態系の大きな焦点はPhoenix , フル機能のWebフレームワークに似てRuby on Rails . フェニックスは、ソフトウェアの素晴らしい作品であり、間違いなくWebアプリケーションの構築に役立ちます.またmodular そして、その機能の小さなサブセットを必要とするならば、あなたはそれのすべての部分を使用する必要はありません.
それに加えて、エリクサーは、他の多くのユースケースにも適していますembedded software .
しかし、言語の学習を開始するには、それ自体が最初に言語自体に焦点を当て、フェニックスや他の抽象化については、言語の上に構築について学ぶことがより有用です.
Elixirでワークフローとツーリングのための感覚を得るために、私は本当に基本的な例プロジェクトを作成しました.
prepend は非常にシンプルなコマンドラインツールであり、指定された文字列をstdINで受信した行に対して与え、stdOUTに書き込む.
次のようにします.
$ echo -e "ice cream\npizza\ncats" | ./prepend "I like "
I like ice cream
I like pizza
I like cats
このCLIのような単純なエリクサーアプリケーションを作成するにはMix , Elixirの組み込みツールmix new prependすべてのビルド構成と依存関係はmix.exs .
ファイルを編集するescript これにより、エリクキアそのものとすべての追加の依存関係を含んだElxirプロジェクトから単一のファイルを構築できます.
あなたが依存関係なしで本当に単純なスクリプトを書いて、あなたがEllxirをインストールしたならば、あなたは.exs そして、コンパイルせずに直接Elixirスクリプトとして実行します.elixir myscript.exs .
実際のコードを書く前にcredo そして、私のエディタがインラインの警告を示すことを確認しました
また、自動的に実行するエディタを設定します mix format だから私はそれについて心配する必要はありません.
stdinとstdoutから読んだり書いたりするためには、 IO.Stream モジュールとドキュメントでは Enumerable , 入力を変換するためのプロトコルです.
入力を変換するには Stream モジュール Enum - それは怠惰に動作し、最初に入力からすべてを読むことなく一度に1行を処理することができます.こうprepend より高速なファイルを処理することができますし、一貫したメモリ使用量の大きなファイルでも.
以来Enumerable は、実際の標準入出力を使用せずにコアロジックを最初に実装できるプロトコルです.
私は最初にreplで物事を試してみることを決めた.
エリクシールIEx .
入力することによってどこでもreplを始めることができますiex .
以来lists 実装Enumerable 実際の行を使う前に実験します.
iex> ["one", "two"] |> Enum.map(&("$ " <> &1))
["$ one", "$ two"]
ここの実際のロジックは超簡単です、しかし、実験のために、私は使用しなければなりませんでしたEnum 出力からStream 以下のようになります.
iex> ["one", "two"] |> Stream.map(&("$ " <> &1))
#Stream<[enum: ["one", "two"], funs: [#Function<48.58052446/1 in Stream.map/2>]]>
でもStream 結果を抽出した後に見ることができる正しいものもあります.
iex> ["one", "two"] |> Stream.map(&("$ " <> &1)) |> Enum.to_list()
["$ one", "$ two"]
新しいプロジェクトを作成するとき、Mixは自動的にlib/ ディレクトリ.
私は、そこで関数としてreplから私のコードを加えました:
def stream_lines(in_stream, str) do
  in_stream |> Stream.map(&(str <> &1))
end
今、私はプロジェクトでREPLを始めることができますiex -S mix そしてモジュールと直接再生します.
["one", "two"] |> Prepend.stream_lines("$ ") |> Enum.to_list
["$ one", "$ two"]
コード内の何かを変更した後、私は常にタイプr Prepend REPL内のコードをリロードし、すべてがまだ動作しているかどうかを確認します.iex その他の便利なショートカットなどh ドキュメントを検索するにはh Stream.map .
私が発見した別の本当にクールなツールは:observer.start .
これは、実際にはErlLirではなくErlangから来ているGUIを起動しますが、それはあなたがあなたのアプリケーションの状態と基本的なランタイムについて知りたいと思うすべての詳細を示しています.
CLISではなく、実行中のアプリケーションを書くとき、iex replと同じツールを使用します.
仕事を包んだPrepend イン Prepend.CLI モジュールを起動時にシステムから引数を受け取り、IO.stream . これは私が実際に追加したモジュールですescript 設定とコマンドラインから直接テストしました.
しかし、私はそこで止まりませんでした.私はテストとしてREPLから私の実験を再利用し、テストのさまざまな方法を探ることを決めた.
私は、単純なテストを加えましたtest/prepend_test.exs :
test "handles multiple words" do
  expected = ["I like ice cream", "I like pizza", "I like cats"]

  received =
    ["ice cream", "pizza", "cats"]
    |> Prepend.stream_lines("I like ")
    |> Enum.to_list()

  assert received == expected
end
私は再タイプしたくなかったのでmix test その間、私はインストールしました mix_test_watch . それは私が保存を押すたびにテストを再実行します.
次に、私の関数を文書化し、doc文字列の例として直接テストを追加することもできます.
@doc """
Prepend the given string to each line if a stream
and returns a stream of the resulting lines.

## Example:

iex> ["one", "two"] |> Prepend.stream_lines("$ ") |> Enum.to_list
["$ one", "$ two"]

"""
また、標準ライブラリのドキュメントで見たのと同じように、私の関数にタイプスペック注釈を追加しました.
@spec stream_lines(Enumerable.t(), String.t()) :: Enumerable.t()
使用するDialyxir 型のエラーをチェックするには
Dialyxirはアーランツールの周りラッパですDialyzer , これは、すべての言語のビーム上で実行して動作します.エリクサーとErlang生態系がどれくらいよく働くかについて見ることは素晴らしいです、そして、それは多くの戦い証明されたツールとライブラリを使うのを許します.
この後、モジュールを使用してプロパティテストをStreamData パッケージ
@tag timeout: 300_000
  property "streams" do
    check all lines <- list_of(string(:printable)),
              prefix <- string(:printable),
              max_runs: 1000 do
      lines
      |> Prepend.stream_lines(prefix)
      |> Stream.each(&String.starts_with?(&1, prefix))
    end
end
私はテストをするためのタイムアウトをmax_runs そして、走るたびに、これを実行したくなかったmix test だから変更test/test_helper.exs プロパティーテストを除外するには、次の手順に従います.
ExUnit.start(exclude: [:property])
これらは明示的に実行できます.mix test --only property最後に私はモジュールをラップしましたMix task .
このようにしてプロジェクトディレクトリ内から使用できますmix prepend 直接最初にバイナリをコンパイルする代わりに.
これは過度に設計された解決策との些細な例ですが、私は開始の容易さと利用可能なツールのシンプルさを楽しんだ.
すべてのソースコードはGithub そして、私は私が失敗して、私の解決に関するフィードバックを得るツールについて聞くのが好きです.私は、物事をするより慣用的な方法があると確信しています、そして、私は物事をするエリクサー方法について知ることがうれしいです.
(Unsplashの上のDaniele Levis Pelusiの写真)