少し前まで、新しいプログラミング言語を学ぶことで考え方を変えることにしました。 私はキャリアの最初からJavaで働いていましたが、今ではまったく異なるパラダイムの必要性を感じ始めました。 それで、私はElixirという素晴らしい言語に出会いました。
ルビストにとって、この言語の名前はよく知られています。また、おそらく作成者の名前はホセ・バリマです。 ただし、より冗長な言語を使用している人は、Elixirに精通する可能性が低くなります。
それで、JavistsがElixirの仕組みをすばやく理解できるように、いくつかの投稿を書くことにしました。 これら2つの言語を比較することで、新しい世界を理解するのが簡単になります。 これらの投稿を通して、構文、言語の仕組み、そしてElixirを本当に素晴らしいものにする主な機能について説明します!
関数型プログラミング
しばらくの間、オブジェクト、クラス、インターフェースを忘れてください。 Elixirは、免疫の原則に基づいてコンパイルされた関数型プログラミング言語です。 3つの単純なルールを覚えておけば、すべてがどのように配置されているかを理解できます。
- データは不変です。
- 関数はi等です。 これは、同じ引数で関数をどれだけ呼び出しても、常に同じ結果が返されることを意味します。
- パターンマッチングを長生きさせます!
こんにちは世界!
どんな言語を勉強しても、始まりはいつも同じです-「Hello world!」。 まあ、そして、我々は車輪を再発明しません。
// Java public class HelloWorld { public static void main(String[] args){ System.out.println("Hello world!"); } }
# Elixir IO.puts "Hello world!"
タイプと変数
Elixirの変数のタイプは、プログラムの実行中に動的に決定されます。 つまり、変数の宣言時に変数の型を明示的に設定する必要はありませんが、型ごとに特定のルールがあります。
// Java int i = 1; float f = 3.0f; boolean b = true; int[] array = {}; String s = "foo"; Map<String, Integer> map = new HashMap<>();
# Elixir i = 1 f = 3.0 b = true list = [1, 2] s = "foo" map = %{"one" => 1, "two" => 2} tuple = {1, 2} keyword_list = [one: 1, two: 2]
次にリストを作成し、新しい要素を追加します。 これは、Javaでの表示方法です。
// Java List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.size(); // 2
最初のルール- 免疫のルールを思い出します。 変数の値を変更するには、別の変数に再度バインドする必要があります。 次の例では、最初の3行のみがリストアイテムの値を変更し、新しい値でコピーが既に作成されています。
# Elixir list = [] # list = [1 | list] # 1 list = [2 | list] # 2 Enum.into(list, [3]) # 3 list ++ [3, 4] # , [2, 1, 3, 4] Enum.count(list) # 2
Elixirのリストに関する小さなヒント: それらはリンクリストとしてメモリに保存されます 。 リストの先頭へのリンクしかないため、新しい要素をリストに追加するには、先頭に挿入してリストの先頭を置き換える必要があります。 これにより、挿入がO(1)
完了することが保証されます。 要素を最後に追加する場合は、上記のように、現在のリストとリストにラップされた新しい要素を連結する必要があります。 しかし、これをより慎重に行うと、リスト全体をコピーして新しいリストを作成するために大量のメモリが必要になるため、操作は簡単ではありません。
もう1つのパズルは、リストの長さを決定することです。 ご想像のとおり、これを行う唯一の方法は、リスト全体を調べて要素の数をカウントすることです(複雑さO(n)
)。 繰り返しますが、注意してください。
心配しないでください、あなたの心だけが命令的な方法ですべてを見ることに慣れています。 この要素のカウント方法に加えて、後で説明する他の方法があります。 それまでの間、悪名高い会社のスローガンを聞いてみましょう。
違った考え方を!
関数とメソッド
4つのアクセス修飾子( public
、 default
、 protected
またはprivate
)のいずれかを持つことができるJavaメソッドとは異なり、Elixirの関数は2つのタイプ( public
またはprivate
)のみです。 パブリック関数とプライベート関数の定義はdefp
それぞれ単語def
とdefp
始まります。 例:
// Java public void addElement(List<Integer> list, Integer element){ list.add(element); } private int privateSum(int a, int b){ return a + b; }
# Elixir def say_hello(person) do "Hello #{person}" end def prepend_element(list, element) do [element | list] end def sum(a, b), do: a + b def sum a, b, c do a + b + c end defp sum(a, b, c, d) do a + b + c + d end
したがって、 return
キーワードを指定する必要なく、関数をさまざまな方法で定義できます。 すべての理由は、関数にアクセスすると、その中の最後のコマンドの結果が常に返されるためです。
上記の関数を使用して、リストに新しい要素を追加してみてください。 Javaの各オブジェクトはポインターであるため、オブジェクトをメソッドに渡すと、このポインターの作成されたコピーがメソッド内の引数として使用されます。 これは、リストの値がaddElement
に再割り当てされるまで、リストで発生した変更がメソッドの外部に表示されることを意味します。 Elixirでは、すべてが完全に異なります。
2番目のルールを覚えていますか? 関数はi等です! 返された結果を除いて、関数内で発生するすべてがそこに残ります。 これはElixirの主な機能の1つであり、コードを分離して実行できるため、まったく新しいレベルの並列処理を実現できます。 また、コードの副作用について心配する必要もありません。
# Elixir list = [1, 2] prepend_element(list, 3) prepend_element(list, 4) prepend_element(list, 5) IO.inspect(list) # [1, 2]
パイプ演算子は言うまでもありません|>
。 これを使用すると、簡単かつ簡単に関数をチェーンに結合し、前の関数の結果を引数として次の関数に渡すことができます。 その使用の最も簡単な例を挙げます。
// Java String fullName = "my full name"; String[] names = fullName.split(" "); String firstName = names[0]; firstName.toUpperCase();
# Elixir "my full name" |> String.split |> List.first |> String.upcase
モジュールとクラス
Javaで何かを実装するには、まずコンストラクター、メソッド、および変数を含むクラスを作成する必要があります。 Elixirでは、コードは機能を単一の全体に結合するモジュールで構成されています。 すべて次のようになります。
// Java class Calculator { public int sum(int a, int b){ return a + b; } }
# Elixir defmodule Calculator do def sum(a, b), do: a + b end
クラス内のモジュールと関数、および静的メソッドの間に平行線を引くことができます。 インスタンスの概念はないため、各モジュールと各関数は「静的」です。 これらの使用法の違いを次の例で示します。
// Java Calculator calculator = new Calculator(); calculator.sum(1, 2);
# Elixir Calculator.sum(1, 2) # Calculator.sum 1, 2
翻訳者からの結論
言語に興味があるなら、ニュースレターを購読してください。月曜日から、初心者向けの包括的な情報サポートから、洗練されたデベロッパー向けの求人情報やオープンソースに至るまで、最も興味深い週があります。
ご清聴ありがとうございました!