Elm は、 Web ブラウザベースのグラフィカル ユーザー インターフェイスを宣言的に作成するためのドメイン固有のプログラミング言語です。Elm は純粋に関数型であり、使いやすさ、パフォーマンス、堅牢性を重視して開発されています。Elmコンパイラの静的型チェックにより、 「実際には実行時例外がない」 [ 10 ]と謳われています。
Elm は、2012 年に Evan Czaplicki が論文として最初に設計しました。[ 11 ] Elm の最初のリリースには、多くのサンプルとWeb ブラウザで簡単に試せるオンライン エディタが付属していました。[ 12 ] Czaplicki は2013 年にPreziに入社しElm の開発に取り組み、[ 13 ] 2016 年にNoRedInkにオープンソース エンジニアとして移籍し、Elm Software Foundation も設立しました。[ 14 ]
Elm コンパイラの初期実装は、HyperText Markup Language ( HTML )、Cascading Style Sheets (CSS )、およびJavaScript を対象としています。[ 15 ]コアツールのセットは拡張を続け、現在ではread–eval–print ループ(REPL)、[ 16 ]パッケージマネージャ、[ 17 ]タイムトラベルデバッガ、[ 18 ]およびmacOSとWindows用のインストーラが含まれています。[ 19 ] Elm には、コミュニティによって作成されたライブラリのエコシステム、[ 20 ]および保存された作業やコミュニティライブラリの組み込みを可能にする高度なオンラインエディタである Ellie もあります。[ 21 ]
Elm には、従来の if 式、ローカル値を格納する let 式、パターン マッチングのための case 式など、少数の言語構成要素があります。[ 22 ]関数型言語として、匿名関数、引数としての関数、関数が関数を返す機能をサポートしており、後者は多くの場合、カリー化された関数の部分適用によって実現されます。関数は値渡しで呼び出されます。その意味論には、不変値、ステートレス関数、型推論による静的型付けが含まれます。Elm プログラムは仮想 DOM を介して HTML をレンダリングし、「JavaScript as a service」を使用して他のコードと相互運用できます。
Elm のすべての値は不変であり、つまり、値は作成後に変更することはできません。Elm は、標準ライブラリで配列、セット、辞書を実装するために永続的なデータ構造を使用します。 [ 23 ]
Elmは静的型付け言語です。型推論があるため、型注釈は必須ではありませんが、強く推奨されます。型注釈は定義のすぐ上の行に記述されます(型と名前が混在するC系言語とは異なります)。Elmでは、単一のコロンで「型を持つ」という意味を表します。
型には、整数や文字列などのプリミティブ型、リスト、タプル、レコードなどの基本的なデータ構造が含まれます。関数には、矢印で記述された型があります。たとえば、 です。カスタム型を使用すると、プログラマーは問題領域に合わせてデータを表現するためのカスタム型を作成できます。[ 24 ]round : Float -> Int
型は、たとえば のように、他の型を参照できますList Int。型は常に大文字で始まります。小文字の名前は型変数です。たとえば、 は、List a型が不明な値のリストです。これは、空のリストと の引数の型でありList.length、リストの要素には依存しません。プログラマーが Elm ランタイムとやり取りするために作成する特別な型がいくつかあります。たとえば、 は、Html Msgイベント ハンドラがすべて 型のメッセージを生成する (仮想) DOM ツリーを表しますMsg。
Elmの標準ライブラリでは、 JavaScriptのnullundefinedやnullポインタMaybe aのように、あらゆる値が暗黙的にnullになる可能性を許容するのではなく、型を定義しています。オプショナル値を生成または処理するコードは、この型を明示的に使用して処理を行い、他のすべてのコードでは、主張された型の値が実際に存在することが保証されます。
Elm には、限られた数の組み込み型クラスが用意されています。numberこれには、やなどの数値演算子の使用を容易にするためのIntとが含まれます。には、比較演算子の使用を容易にするための数値、文字、文字列、比較可能なもののリスト、および比較可能なもののタプルが含まれます。には、との連結を容易にするための文字列とリストが含まれます。Elm は、これらの型クラスにカスタム型を含めたり、新しい型クラスを作成したりするメカニズムを提供していません (制限事項を参照)。Float(+)(*)comparableappendable(++)
Elmには、ユーザーがコードをモジュールと呼ばれる小さな部分に分割できるモジュールシステムBitwise.andがあります。モジュールは、ヘルパー関数などの実装の詳細を隠蔽し、関連するコードをグループ化できます。モジュールは、インポートされたコードの名前空間として機能します。サードパーティライブラリ(またはパッケージ)は1つ以上のモジュールで構成され、Elmパブリックライブラリから入手できます。すべてのライブラリは、コンパイラやその他のツールによって強制されるセマンティックバージョニングに従ってバージョン管理されています。つまり、関数の削除や型の変更は、メジャーリリースでのみ実行できます。
Elm はJavaScriptと通信するためにポートと呼ばれる抽象化を使用します。[ 25 ]これにより、Elm プログラムへの値の出入りが可能になり、Elm と JavaScript 間の通信が可能になります。
Elmにはelm/htmlというライブラリがあり、プログラマーはこれを使ってElm内でHTMLとCSSを記述できます。[ 26 ]更新を効率化するために仮想DOMアプローチを使用しています。 [ 27 ]
Elm は公式にはサーバーサイド開発をサポートしていません。Czaplicki 氏はこれを主要な目標と考えていますが、この分野での公的な進展は遅いです。それでも、バックエンドで Elm を探求しようとする独立したプロジェクトがいくつかあります。[ 28 ]
主要なフルスタックElmプラットフォームは、Elmのオープンコア「アンフォーク」であるLamderaです。[ 29 ] [ 30 ] [ 31 ] Czaplickiは、Lamderaの代替となる可能性のあるElm Studioも予告していますが、まだ一般には公開されていません。[ 32 ] Czaplickiのデモでは、型安全なPostgresテーブル生成をサポートする将来のバージョンのElmが使用されているようです。[ 33 ]また、将来のバージョンのElmはCにコンパイルされ、Emscriptenを使用してWASMを生成するという憶測もありますが、これはCzaplickiによって確認されていません。[ 34 ]
BaaS製品とは対照的に、フルスタックフレームワークの場合、elm-pagesはおそらく最も人気のある完全オープンソースのオプションです。[ 35 ]これはElm言語を拡張するものではなく(前述のLamderaコンパイラのオープンソースコンポーネントを使用していますが)、コンパイルされたJavaScriptをNode.js上で実行します。また、APIを使用したスクリプトもサポートしていますBackendTask。Elmから.NETへのコンパイラであるPineもあり、C#、F#、その他のCLR言語との安全な相互運用が可能です。[ 36 ]
Elm 0.19.0 より前のバージョンでは、BEAM (Erlang 仮想マシン)を使用してElm を実行しようとする試みもありましたが、0.19.0 でネイティブコードが削除され、パッケージマネージャが変更されたため、現在は機能していません。あるプロジェクトでは Elm を環境上で直接実行し[ 37 ]、別のプロジェクトでは Elxir にコンパイルしていました[ 38 ] 。
Elmアーキテクチャは、インタラクティブなWebアプリケーションを構築するためのソフトウェア設計パターンであり、略称ではTEAパターンと呼ばれます。Elmアプリケーションは自然とこの方法で構築されますが、他のプロジェクトでもこの概念が役立つ場合があります。
Elmプログラムは常に3つの部分に分かれています。
これらがエルム・アーキテクチャーの中核を成すものです。
例えば、数字と、押すと数字を増やすボタンを表示するアプリケーションを想像してみてください。[ 39 ]この場合、保存する必要があるのは 1 つの数字だけなので、モデルは のようにシンプルにできます type alias Model = Int。view関数はライブラリで定義され、数字とボタンを表示します。数字を更新するには、などのカスタム型を使用して、関数Htmlにメッセージを送信できる必要があります。 値は、 関数で定義されたボタンに添付され、ユーザーがボタンをクリックすると、が 関数に渡され、関数は数字を増やすことでモデルを更新できます。updatetype Msg = IncreaseIncreaseviewIncreaseupdate
Elmアーキテクチャでは、メッセージを送信すること updateだけが状態を変更する唯一の方法です。より高度なアプリケーションでは、メッセージはさまざまなソースから発生する可能性があります。ユーザー操作、モデルの初期化、からの内部呼び出しupdate、外部イベント(ウィンドウのリサイズ、システムクロック、JavaScriptとの相互運用など)の購読、URLの変更とリクエストなどです。
Elm は、関連言語であるHaskell、Scala、PureScriptが提供する高階多相性をサポートしておらず[ 40 ]、型クラスの作成もサポートしていません。
これは、例えば Elm には、やmapなどの複数のデータ構造にまたがって機能する汎用関数がないことを意味します。Elm では、このような関数は通常、モジュール名で修飾されて呼び出されます。例えば、やを呼び出します。Haskell や PureScript では、関数は 1 つだけです。これは、少なくとも 2015 年以来 Czaplicki の概略ロードマップに記載されている既知の機能リクエストです。[ 41 ]一方、Scalaのような高度な言語での TEA パターンの実装は、このような制限を受けず、Scalaの型クラス、型レベルおよび種類レベルのプログラミング構造の恩恵を受けることができます。[ 42 ]ListSetList.mapSet.mapmap
もう1つの結果として、中規模から大規模のプロジェクトでは大量の定型コードが発生しています。これは、元Elmコアチームメンバーである「Elm in Action」の著者が、シングルページアプリケーションの例[ 43 ]で示したとおりで、更新、ビュー、サブスクリプション、ルート解析、構築関数でほぼ同じ断片が繰り返されています。
-- これは1行のコメントです。これは複数行コメントです。ネスト可能です。-- ここでは、`greeting` という名前の値を定義します。型は `String` として推論されます。greeting = "Hello World!"-- トップレベルの宣言に型注釈を追加するのが最善です。hello : String hello = "こんにちは。"関数は同じように宣言され、引数は関数名の後に続きます。add x y = x + y-- 繰り返しになりますが、型注釈を追加するのが最善です。hypotenuse : Float -> Float -> Float hypotenuse a b = sqrt ( a ^ 2 + b ^ 2 )-- `\[arg] -> [expression]` 構文でラムダ関数を作成できます。hello : String -> String hello = \ s -> "Hi, " ++ s-- 関数宣言には、`_` で示される匿名パラメータ名を含めることができます。-- これらは一致しますが、本体では使用されません。const : a -> b -> a const k _ = k-- 関数もカリー化されます。ここでは、乗算演算子を `2` でカリー化しています。 multiplyBy2 : number -> number multiplyBy2 = (*) 2-- if 式は `Bool` 値に基づいて分岐するために使用されますabsoluteValue : number -> number absoluteValue number = if number < 0 then negate number else number-- レコードは、名前付きフィールドを持つ値を保持するために使用されます。book : { title : String , author : String , pages : Int } book = { title = "Steppenwolf" , author = "Hesse" , pages = 237 }-- レコードへのアクセスは `.` で行います。title : String title = book . title-- レコードアクセス `.` は関数authorとしても使用できます: String author = . author book-- `type` キーワードを使用してタグ付き共用体を作成できます。-- 次の値は二分木を表します。type Tree a = Empty | Node a ( Tree a ) ( Tree a )-- ケース式を使用してこれらの型を検査できます。depth : Tree a -> Int depth tree = case tree of Empty -> 0 Node _ left right -> 1 + max ( depth left ) ( depth right )スタイルに詳しい方は、更新された--explainメッセージがElmのアプローチから大きな影響を受けていることに気づくかもしれません。
Roc は Elm プログラミング言語の直接の子孫です。この 2 つの言語は似ていますが、同じではありません。