SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Webアプリケーション開発技術の新潮流スタディーズ

関数型リアクティブプログラミング言語Elmに学ぶ フロントエンド開発の新しい形 【前編】

Webアプリケーション開発技術の新潮流スタディーズ 第4回


その他の構文

if ~ then ~ else

case ... ofと同様にifも値を返します。JavaScriptの条件演算子(?)と同じです。

max a b = if a > b then a else b

また、if ~ then elseは次のように書くこともできます。

fizzbuzz n =
  if | n % 15 == 0 -> "FizzBuzz"
     | n % 5 == 0 -> "Buzz"
     | n % 3 == 0 -> "Fizz"
     | otherwise -> toString n

let ~ in

関数の中身が長くなる場合にはlet ~ inを使って、一時的に用いる変数を宣言することができます。 変数の宣言をletの後ろで行い、inの後ろに宣言した変数を使う処理を記述します。

distance a b =
  let
    -- 一時的な変数を宣言します
    -- dx, dyは外部からアクセスできません
    dx = b.x - a.x
    dy = b.y - a.y
  in
    -- 計算結果を返します
    sqrt (dx^2 + dy^2)

import ~ exposing ( ~ )

importにより、モジュールをインポートして使えるようになります。

import List

len = List.length [1,2,3] -- 3

次のコードでは、モジュールに定義された関数を直接使えるようにしています。

import List exposing (length, reverse)
import Html exposing (..) -- 全ての定義をインポート

len = length [1,2,3] -- List.length

reversed = reverse [1,2,3] -- List.reverse

main = text (toString len) -- Html.text

Elmの組み込み標準モジュールやサードパーティのライブラリはパッケージカタログにて公開されています。 これらのうち、標準的な型や関数はimportなしで使えます。

関数型プログラミング

高階関数とラムダ式

次に、関数型プログラミングに慣れるために「関数を引数に取る関数」を見ていきましょう。以下は、リスト操作に頻出するList.map関数の使用例です。

-- List.map : (a -> b) -> List a -> List b
-- toString : a -> String

stringNumbers : List String
stringNumbers = List.map toString [1,2,3] -- ["1","2","3"]

List.mapは、リスト中の全ての値に関数を適用し、新しいリストを生成します(JavaScriptのmap関数と同じです)。

型の記述についても慣れておきましょう。 (a -> b) -> List a -> List bは、aにInt型、bにString型を当てはめると、(Int -> String) -> List Int -> List Stringとなります。つまり、「第1引数にInt型をString型にする関数、第2引数にInt型のリストを取り、String型のリストを返す」関数になります。

次の例では、ラムダ式を使ってその場で関数を生成しています。

doubledNumbers = List.map (\n -> n * 2) [1,2,3] -- [2,4,6]

(\n -> n * 2)は、nを引数にとり、2倍して返す関数を表しています。

中置演算子は関数

+*::などの中置演算子は、通常の関数と同じように使うことができます。

-- (+) : number -> number -> number
n = (+) 1 2 -- 1 + 2 と同じ

その他の演算子

|>はパイプ演算子とも呼ばれ、関数を連続して適用するときに便利な演算子です。 今すぐ書けるようになる必要はありませんが、時々出てくるので読めるようにしておきましょう。 以下の例において上下は同じ意味です。

import String exposing (..)

len1 = length (repeat 3 (trim " HEY! ")) -- 12

len2 = " HEY! " |> trim |> repeat 3 |> length

また、trimからlengthまでを先に合成してから関数を適用するには>>を使います。

len3 = (trim >> repeat 3 >> length) " HEY! "

先ほど触れたように、これらの演算子の正体は関数です。それぞれの定義はパッケージカタログを参照してください。

Hello, world!

お疲れ様でした。以上でElmの基本的な構文説明は完了です。 今回は、ブラウザ上でElmプログラムを実行できる「Try Elm」を利用します。以下のコードを貼り付けて[Compile]ボタンを押してみてください。 無事、Hello, World!が画面に表示されているでしょうか。

import Html exposing (..)

main : Html
main = text "Hello, World!" -- Html.text : String -> Html

Elmでは、画面へのアウトプットをmain関数に記述します。 main関数は、HtmlSignal HtmlElementSignal Elementという限られた型[4]のみが許されています。

Html.textは文字列を受け取りテキストノードを生成する関数です。少し味気ないと思いますので、試しに次のようにしてみましょう。

import Html exposing (..)
import Html.Attributes exposing (..)

url = "http://elm-lang.org/"

main : Html
main =
  div
    []
    [ h1 [style [("color", "green")]] [text "Hello, World!"]
    , text "(written in "
    , a [href url, target "_blank"] [text "Elm"]
    , text ")"
    ]

ここで登場するdivh1などは、全てelm-htmlパッケージが提供する関数です。

さてここまで、Elmの基本的な書き方について解説してきました。 慣れるまではいろいろ試してみるとよいでしょう。

次のページでは、FRPの基本となる「Signal」という機構を使って動く画面を作る方法を見ていきます。

[4]: これらの型を、モジュール名を省略しないで記述した場合、それぞれ、Html.HtmlSignal Html.HtmlGraphics.Element.ElementSignal Graphics.Element.Elementになります。

Graphics.ElementモジュールとHtmlモジュール

Elmは歴史的な理由から、Graphics.ElementHtmlという2種類の基本的なモジュールを備えています。 前者はElmの登場した当時から存在するもので、色や位置を独自の関数で記述し、HTMLを隠蔽します。 一方、後者は「elm-html」パッケージにより導入され、HTMLタグを直接記述することができます。 今からElmでWebアプリケーションを作るのであれば、最初は後者のHtmlを使うことをお勧めします。 既存のWeb開発のノウハウをそのまま活かせますし、Twitter BootstrapなどのCSSフレームワークも難なく使えます。 とはいえ、Graphics.Elementも図形描画のための便利な関数が多数用意されており、まだまだ現役です。

次のページ
FRPの基本となるSignal

修正履歴

この記事は参考になりましたか?

Webアプリケーション開発技術の新潮流スタディーズ連載記事一覧

もっと読む

この記事の著者

鳥居 陽介(株式会社ワークスアプリケーションズ)(トリイ ヨウスケ)

株式会社ワークスアプリケーションズ所属。イケてるアプリケーションを死ぬほど楽に作るために研究を続ける日々。社内での立ち位置は「フロントエンドのナウい人」。最近エバンジェリストという肩書きが付いた。趣味は作曲とスノーボード。 Blog: http://jinjor-labo.hatenablog.com/ ...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/8873 2017/03/02 16:39

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー