1659092821
Elmはおそらく私のお気に入りのプログラミング言語です。その意見はありますが、歓迎的なデザインは、言語デザインが開発者を保守可能なコードの記述に向けて優しく導く方法についての説得力のあるケーススタディを提供します。
Elmは、フロントエンドアプリケーションを作成するために設計された言語であり、ReactなどのJavaScriptライブラリに代わるものを提供します。どちらも2012年頃に作成され、Elmは学術論文プロジェクトとして、Reactは業界が支援するライブラリとして作成されました。両方の基盤となるテクノロジーは、仮想DOMとユーザーインターフェイスを作成するための宣言型プログラミングスタイルです。2つの主な違いは、ReactはJavaScript用に構築された単なるライブラリであるのに対し、Elmはドメイン固有言語全体であり、目的のためにゼロから設計されていることです。
つまり、Elmには、不変性、ラムダ関数、型の安全性など、JavaScript開発のベストプラクティスと見なされているいくつかの言語機能があります。しかし、ElmはReactやTypeScriptよりも多くの点で進歩しており、「実際にはランタイムエラーがない」ことを誇るほど強力な型システムを備えており、競合他社よりも大幅に速度が向上しています。
TypeScriptの人気が高まるにつれ、他のどのElm機能がReactに移行するのだろうかと思います。私の個人的な希望は、有名なフレンドリーなエラーメッセージ(下の画像を参照)が言語に反映されることです。Elmはコンパイルされた言語であるため、コードが変更された後にコンパイラーが再実行され、ブラウザー用のJavaScriptが生成されます。これは障害のように思えますが、開発ループは非常に魅力的だと思います。コンパイラが作業のガイドを支援し、開発者にコードへの信頼を高める一種の「タイプ駆動型開発」です。この「ライブ再コンパイル」は、Elmの超高速のタイプチェックとコンパイルによって可能になりましたが、TypeScriptにはまだひどく欠けているものがあります。
プログラミング言語の採用の歴史は、今日の流行言語が純粋な偶然によって、または企業のマーケティングキャンペーンの結果として成功することが多いため、人気のあるものが常に最良であるとは限らないことを示しています。業界は関数型プログラミングに向かっていると私は心から信じています。Reactの作成者であるJordanWalkeは、ReasonML(Elmに密接に関連する関数型言語)は「Reactの言語」であると自分自身に言いました。彼は、Reactが成功した後、もう一度関数型プログラミングに目を向け、「他に何を見逃したのか」と尋ねるべきだと考えています。
Reactに精通している開発者が構文を理解できるように、同じアプリケーションをElmとReactで記述しました。これは、インクリメントボタンとデクリメントボタンを備えたカウンターです(単純化するために、両方からボイラープレートコードとインポートステートメントを少し除外しました)。もの)。ページは次のようになります。
const App = () => {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
return (
<div>
<button onClick={decrement}>-</button>
{count}
<button onClick={increment}>+</button>
</div>
);
};
type Msg = Increment | Decrement
init = { count = 0 }
update msg model =
case msg of
Increment -> { model | count = model.count + 1 }
Decrement -> { model | count = model.count - 1 }
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, text (String.fromInt model.count)
, button [ onClick Increment ] [ text "+" ]
]
ご覧のとおり、2つのプログラムは多くの点で類似しており、他のプログラムではまったく異なります。やや異質なMLスタイルの構文に苦労している場合は、このクイック構文ガイドを確認してください。
まず、Msg
型をIncrement
またはDecrement
値のいずれかに定義します。これについては後で詳しく説明します。
その後、Elmプログラムは、3つの自己完結型関数定義、、、に分割さinit
れupdate
ますview
。これは、すべてが1つの関数に含まれているReactとは対照的です。
このinit
関数は、Reactアプリの2行目によく似ています。モデルの初期状態、基本的にはアプリケーション全体の状態のデータ型を定義します。Reactのフックを使用する場合とは異なり、後で説明する理由により、アプリケーション全体のすべての状態を1つのデータ構造に格納することをお勧めします。
次に、関数はモデルとメッセージupdate
の2つの引数を取ります。次に、受信したメッセージに基づいてモデルを変更する方法を決定し、カウントが変更されたモデルの新しいコピーを返します。コードは、 「カウントが1つ大きいモデルのコピー」として読み取ることができます。Elmは、ボタンを押すなどして新しいメッセージが送信されるたびに、この関数を呼び出します。{ model | count = model.count + 1 }
最後に、view
関数は1つの引数Modelを取り、それをHTMLとしてレンダリングします。スタイルを除けば、これはReact関数のreturnステートメントとほとんど同じです。ただし、Elmでは、ボタンがラムダを呼び出すのではなくメッセージを送信する点が異なります。Elmは、モデルview
が変更されるたびにページを再レンダリングするように呼び出します。
これらの違いのほとんどは、Elmが純粋に関数型言語であるという事実の結果です。つまり、ReactwithHooksのように「副作用」を実行することは許可されていません。機能の純度は、コードベースに関する重要な保証を提供します。同じ入力が与えられた場合、常に同じ出力が得られることを確信できます。実用的な意味では、これによりコードが読みやすくなります。関数で変更される値はパラメーターのみであることがわかっているため、周囲のコンテキスト全体を読み取るのに時間を無駄にする必要はありません。これが、保守性を損なうことなくElmファイルをJavaScriptファイルよりも長くできる理由の1つです。理解する必要のある最小単位は、モジュール全体ではなく関数であるためです。
ただし、コードをに分離することには、init
他update
のview
利点があります。アプリケーションロジックを記述するコードとその外観を分離することは、言語によって強制されるようになりました。
このガイドでは、この構造を「エルムアーキテクチャ」と呼んでいます(上の図を参照)。Elmランタイムはアプリケーションを管理しview
、モデルが変更されるたびに、update
メッセージを受信するたびに呼び出します。ここでのインタラクションは、Elmに触発されたReduxのユーザーにはおなじみです。ここで、Reduxの「アクション」はElmメッセージにほぼ近似しており、 「レデューサー」update
に似ています。
大きなモジュールでこれらのタイプを変更すると、コンパイラは後で更新が必要なすべての場所を警告し、コードベースを手動で検索するタスクから解放されるため、一元化されたメッセージタイプとモデルタイプを使用すると生産性が向上します。状態を単一のモデルに一元化することには、アーキテクチャ上の利点もあります。これにより、違法な状態を表現不可能にすることができ、Webページのすべての動的な側面を徹底的に説明する必要があります。このようにアプリケーションの状態をデータ構造としてモデル化することは強力なツールであり、アプリケーションのコアに実際に何があるかを検討するのに役立ちます。
より厳密な型システムは制限のように見える場合があります。たとえば、Reactでは単純に{count}
、Elmでは書き込みを行い、をaにtext (String.fromInt model.count)
変換します。ただし、TypeScriptのエバンジェリストが言うように、型安全性の利点は、コードの予測可能性を高め、Elmの場合、ランタイムエラーの可能性を排除するため、追加の作業を上回ることがよくあります。IntStringHtml
Elmでは、型は通常、作成したコードから推測できるため、型安全性のメリットを享受するために型アノテーションを作成する必要はほとんどありません。ただし、コードを読みやすくし、コンパイラがより適切なエラーメッセージを表示できるようにするため、多くの場合、これらは優れた方法と見なされます。したがって、興味を引くために、タイプアノテーションを使用した上記のプログラムを次に示します。
type Msg = Increment | Decrement
type alias Model = { count : Int }
init : Model
init = { count = 0 }
update : Msg -> Model -> Model
update msg model =
case msg of
Increment -> { model | count = model.count + 1 }
Decrement -> { model | count = model.count - 1 }
view : Model -> Html Msg
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, text (String.fromInt model.count)
, button [ onClick Increment ] [ text "+" ]
]
まず、モデルに正式な型を与えます。ここでは構文を使用しますtype alias
。これは、(Msgのように)新しい値のセットを導入していないためです。これは、「count」{ count : Int }
と呼ばれる整数フィールドを持つレコードの省略形です。この新しい型を使用して、の宣言に注釈を付け、型の定数であると述べます。initModel
次に、update
型注釈を付けMsg -> Model -> Model
ます。これは基本的に、「更新はメッセージとモデルを受け取り、別のモデルを返す関数です」と言っています。これは、Elm関数がデフォルトで「カレー」されているという事実によってやや難読化されており、実際の意味は「updateはメッセージを受け取り、Modelを受け取り、Modelを返す関数を返す関数」のようになります。
最後にview
、タイプで注釈を付けModel -> Html Msg
ます。これは、view
関数がモデルを受け取り、いくつかのHTML、具体的にはカスタムメッセージが埋め込まれたHTMLを返すことを示しています。これはパラメータ化されたタイプの形式です。TypeScriptに相当するものはHtml<Msg>
です。
ソース:https ://blog.theodo.com/2021/10/intro-to-elm-for-react-devs/
1659092821
Elmはおそらく私のお気に入りのプログラミング言語です。その意見はありますが、歓迎的なデザインは、言語デザインが開発者を保守可能なコードの記述に向けて優しく導く方法についての説得力のあるケーススタディを提供します。
Elmは、フロントエンドアプリケーションを作成するために設計された言語であり、ReactなどのJavaScriptライブラリに代わるものを提供します。どちらも2012年頃に作成され、Elmは学術論文プロジェクトとして、Reactは業界が支援するライブラリとして作成されました。両方の基盤となるテクノロジーは、仮想DOMとユーザーインターフェイスを作成するための宣言型プログラミングスタイルです。2つの主な違いは、ReactはJavaScript用に構築された単なるライブラリであるのに対し、Elmはドメイン固有言語全体であり、目的のためにゼロから設計されていることです。
つまり、Elmには、不変性、ラムダ関数、型の安全性など、JavaScript開発のベストプラクティスと見なされているいくつかの言語機能があります。しかし、ElmはReactやTypeScriptよりも多くの点で進歩しており、「実際にはランタイムエラーがない」ことを誇るほど強力な型システムを備えており、競合他社よりも大幅に速度が向上しています。
TypeScriptの人気が高まるにつれ、他のどのElm機能がReactに移行するのだろうかと思います。私の個人的な希望は、有名なフレンドリーなエラーメッセージ(下の画像を参照)が言語に反映されることです。Elmはコンパイルされた言語であるため、コードが変更された後にコンパイラーが再実行され、ブラウザー用のJavaScriptが生成されます。これは障害のように思えますが、開発ループは非常に魅力的だと思います。コンパイラが作業のガイドを支援し、開発者にコードへの信頼を高める一種の「タイプ駆動型開発」です。この「ライブ再コンパイル」は、Elmの超高速のタイプチェックとコンパイルによって可能になりましたが、TypeScriptにはまだひどく欠けているものがあります。
プログラミング言語の採用の歴史は、今日の流行言語が純粋な偶然によって、または企業のマーケティングキャンペーンの結果として成功することが多いため、人気のあるものが常に最良であるとは限らないことを示しています。業界は関数型プログラミングに向かっていると私は心から信じています。Reactの作成者であるJordanWalkeは、ReasonML(Elmに密接に関連する関数型言語)は「Reactの言語」であると自分自身に言いました。彼は、Reactが成功した後、もう一度関数型プログラミングに目を向け、「他に何を見逃したのか」と尋ねるべきだと考えています。
Reactに精通している開発者が構文を理解できるように、同じアプリケーションをElmとReactで記述しました。これは、インクリメントボタンとデクリメントボタンを備えたカウンターです(単純化するために、両方からボイラープレートコードとインポートステートメントを少し除外しました)。もの)。ページは次のようになります。
const App = () => {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
return (
<div>
<button onClick={decrement}>-</button>
{count}
<button onClick={increment}>+</button>
</div>
);
};
type Msg = Increment | Decrement
init = { count = 0 }
update msg model =
case msg of
Increment -> { model | count = model.count + 1 }
Decrement -> { model | count = model.count - 1 }
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, text (String.fromInt model.count)
, button [ onClick Increment ] [ text "+" ]
]
ご覧のとおり、2つのプログラムは多くの点で類似しており、他のプログラムではまったく異なります。やや異質なMLスタイルの構文に苦労している場合は、このクイック構文ガイドを確認してください。
まず、Msg
型をIncrement
またはDecrement
値のいずれかに定義します。これについては後で詳しく説明します。
その後、Elmプログラムは、3つの自己完結型関数定義、、、に分割さinit
れupdate
ますview
。これは、すべてが1つの関数に含まれているReactとは対照的です。
このinit
関数は、Reactアプリの2行目によく似ています。モデルの初期状態、基本的にはアプリケーション全体の状態のデータ型を定義します。Reactのフックを使用する場合とは異なり、後で説明する理由により、アプリケーション全体のすべての状態を1つのデータ構造に格納することをお勧めします。
次に、関数はモデルとメッセージupdate
の2つの引数を取ります。次に、受信したメッセージに基づいてモデルを変更する方法を決定し、カウントが変更されたモデルの新しいコピーを返します。コードは、 「カウントが1つ大きいモデルのコピー」として読み取ることができます。Elmは、ボタンを押すなどして新しいメッセージが送信されるたびに、この関数を呼び出します。{ model | count = model.count + 1 }
最後に、view
関数は1つの引数Modelを取り、それをHTMLとしてレンダリングします。スタイルを除けば、これはReact関数のreturnステートメントとほとんど同じです。ただし、Elmでは、ボタンがラムダを呼び出すのではなくメッセージを送信する点が異なります。Elmは、モデルview
が変更されるたびにページを再レンダリングするように呼び出します。
これらの違いのほとんどは、Elmが純粋に関数型言語であるという事実の結果です。つまり、ReactwithHooksのように「副作用」を実行することは許可されていません。機能の純度は、コードベースに関する重要な保証を提供します。同じ入力が与えられた場合、常に同じ出力が得られることを確信できます。実用的な意味では、これによりコードが読みやすくなります。関数で変更される値はパラメーターのみであることがわかっているため、周囲のコンテキスト全体を読み取るのに時間を無駄にする必要はありません。これが、保守性を損なうことなくElmファイルをJavaScriptファイルよりも長くできる理由の1つです。理解する必要のある最小単位は、モジュール全体ではなく関数であるためです。
ただし、コードをに分離することには、init
他update
のview
利点があります。アプリケーションロジックを記述するコードとその外観を分離することは、言語によって強制されるようになりました。
このガイドでは、この構造を「エルムアーキテクチャ」と呼んでいます(上の図を参照)。Elmランタイムはアプリケーションを管理しview
、モデルが変更されるたびに、update
メッセージを受信するたびに呼び出します。ここでのインタラクションは、Elmに触発されたReduxのユーザーにはおなじみです。ここで、Reduxの「アクション」はElmメッセージにほぼ近似しており、 「レデューサー」update
に似ています。
大きなモジュールでこれらのタイプを変更すると、コンパイラは後で更新が必要なすべての場所を警告し、コードベースを手動で検索するタスクから解放されるため、一元化されたメッセージタイプとモデルタイプを使用すると生産性が向上します。状態を単一のモデルに一元化することには、アーキテクチャ上の利点もあります。これにより、違法な状態を表現不可能にすることができ、Webページのすべての動的な側面を徹底的に説明する必要があります。このようにアプリケーションの状態をデータ構造としてモデル化することは強力なツールであり、アプリケーションのコアに実際に何があるかを検討するのに役立ちます。
より厳密な型システムは制限のように見える場合があります。たとえば、Reactでは単純に{count}
、Elmでは書き込みを行い、をaにtext (String.fromInt model.count)
変換します。ただし、TypeScriptのエバンジェリストが言うように、型安全性の利点は、コードの予測可能性を高め、Elmの場合、ランタイムエラーの可能性を排除するため、追加の作業を上回ることがよくあります。IntStringHtml
Elmでは、型は通常、作成したコードから推測できるため、型安全性のメリットを享受するために型アノテーションを作成する必要はほとんどありません。ただし、コードを読みやすくし、コンパイラがより適切なエラーメッセージを表示できるようにするため、多くの場合、これらは優れた方法と見なされます。したがって、興味を引くために、タイプアノテーションを使用した上記のプログラムを次に示します。
type Msg = Increment | Decrement
type alias Model = { count : Int }
init : Model
init = { count = 0 }
update : Msg -> Model -> Model
update msg model =
case msg of
Increment -> { model | count = model.count + 1 }
Decrement -> { model | count = model.count - 1 }
view : Model -> Html Msg
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, text (String.fromInt model.count)
, button [ onClick Increment ] [ text "+" ]
]
まず、モデルに正式な型を与えます。ここでは構文を使用しますtype alias
。これは、(Msgのように)新しい値のセットを導入していないためです。これは、「count」{ count : Int }
と呼ばれる整数フィールドを持つレコードの省略形です。この新しい型を使用して、の宣言に注釈を付け、型の定数であると述べます。initModel
次に、update
型注釈を付けMsg -> Model -> Model
ます。これは基本的に、「更新はメッセージとモデルを受け取り、別のモデルを返す関数です」と言っています。これは、Elm関数がデフォルトで「カレー」されているという事実によってやや難読化されており、実際の意味は「updateはメッセージを受け取り、Modelを受け取り、Modelを返す関数を返す関数」のようになります。
最後にview
、タイプで注釈を付けModel -> Html Msg
ます。これは、view
関数がモデルを受け取り、いくつかのHTML、具体的にはカスタムメッセージが埋め込まれたHTMLを返すことを示しています。これはパラメータ化されたタイプの形式です。TypeScriptに相当するものはHtml<Msg>
です。
ソース:https ://blog.theodo.com/2021/10/intro-to-elm-for-react-devs/