構文全体

構文の全体を見てみます。

Elmを簡単に試すにはelm-replを使うのが便利です。サンプルコード中に>とあるものは、elm-replで表示した結果になっています。

コメント

一行コメント

-- comment !!

複数行コメント

{-
  piyo
  piyo  
-}

リテラル

真理値(Bool)はTrueFalseです。

メモ:01Nothingは真理値になりません。

True  : Bool
False : Bool

数値をそのまま書くとnumber(Int、Floatどちらにもなる特殊な型)、少数点をつけるとFloat型になります。

42    : number
3.14  : Float

シングルコーテーションで一文字を表現するChar型に、ダブルコーテーションで文字列型(String)になります。

'a'   : Char
"abc" : String

複数行ある文字列型を扱うにはダブルコーテーションを3つ並べます。


mark : String
mark =
 """
## Usage
 * json
 * markdown
 * etc ..

"""

[],でList型になります。

[1..4]           
[1,2,3,4]
1 :: [2,3,4]
1 :: 2 :: 3 :: 4 :: []

(),でタプル型になります。

> (1,"hello",4)
(1,"hello",4) : ( number, String, number' )

変数、関数の定義

変数

age = 10
word = "Hello World"

関数

add10 : Int -> Int
add10 n = n + 10

helloWorld name name2 = "hello , " ++ name ++ " " ++ name2

関数の適用

> twice n = 2 * n
<function> : number -> number
> twice 10
20 : number

関数を`でくるむと中置き記法ができます。

max 5 10 ==
5 `max` 10

case式、if式、

case式とif式で処理を分岐します。

if式は、条件によって処理が分岐します。

if a < 200 then
    "ok"
else
    "予算over"

case式は、パターンによって処理を分岐します。

case {知りたいもの} of
     {一つ目} -> ...
     {二つ目} -> ...

case n of
    2 ->
    8 ->
    _ -> --_(アンダーバー)はすべてにマッチします。

case式は必ず型を網羅しないといけません。

type Msg
    = Get
    | Move

update msg state =
  case msg of
    Get ->
      --
    Move ->      --全てのパターンを網羅する必要がある
      --

let in式

let in式を使うと、内部変数を定義できます。

test a y =
      let
          x = a * 8
      in  x + y

型の表記

変数や関数には、型を明示することが出来ます。

age : Int
age = 15

word : String
word = "hello"

add10 : Int -> Int
add10 n = n + 10

型の定義

新しい型を定義することができます。

type Id = Id Int
type Fruit = Orange | Peach

type alias を使うと型に別名を付ける事ができます。

type alias Age = Int
type alias Name = String

type User = User Age Name

isOver15 : Age -> Bool

「新しい型を定義する」のページで解説しています。

レコード型

レコード型を定義できます。レコード型はjavasciptのオブジェクトに近いものです。

type alias User = {id : Int , name : String}

init : User
init = {id = 10 , name = ""}

レコード構文

レコード型には専用のアクセスと、更新用の構文があります。

値を取り出す。

> hiro = {hp=10}
{ hp = 10 } : { hp : number }
> hiro.hp
10 : number
> .hp hiro
10 : number

レコード型を更新する。

> hiro = {hp = 100}
{ hp = 100 } : { hp : number }
> {hiro | hp = hiro.hp + 20}
{ hp = 120 } : { hp : number }

モジュール:module

Elmはソースコードを別ファイルに分ける仕組みがあります。

module Test exposing (..) --モジュール名を付けて外にだす。

import Hoge exposing (hello) --モジュールをインポート

exposingの書き方で、内外に出す関数やデータ構築子を細かく指定できます。

module Hello exposing
    ( Hoge(A,B)         --型とその構築子を指定
    , hello             --関数を指定
    )

type Hoge
    = A
    | B
hello = ""
world = ""

import

モジュールをインポートします。書き方によりインポートの仕方が変わります。

-- qualified imports
import String                       
import String as Str                
String.repeat ...

-- unqualified imports  モジュール名を付ける必要がなくなります。
import Hello exposing (..)                -- Hoge , hello , world
import Hello exposing ( Hoge )            -- Hoge
import Hello exposing ( Hoge(..) )        -- Hoge, A , B
import Hello exposing ( Hoge(A) )         -- Hoge, A

「Module:モジュールシステム」のページでも解説しています。

関数の適用順、パイプ演算子

関数には適用される順番がありますが、それを操作するパイプ演算子(<|)、(|>)というのがあります。

hiku2  (add10 3)

== hiku2 <| add10 3

== add10 3 |> hiku2

この演算子を使うと、わかりやすく処理の流れを書くことができます。

dot' =
  circle 10
    |> filled blue
    |> move (20,20)
    |> scale 2

パターンマッチ

パターンマッチとは、表記を合わせれば型から値を取り出すことができる、という構文です。

以下のようなId型あるとして、それを受け取って中の数字を取り出す関数は以下のように書けます。

type Id = Id Int

getNum : Id -> Int
getNum (Id a) = a

引数部分がパターンマッチといわれる書き方で、aの部分にはIdの中身が勝手に入っています。

パターンマッチは関数の引数部分や、case式の部分で出来ます。

type alias Chara = { hp : Int}

HpToStr : Chara -> String
HpToStr {hp} = toString hp    ---レコード型をパターンマッチ

type Msg = Add Int

update msg state =
      case msg of                
        Add n ->              --case式内でパターンマッチ

Port構文

JS側でportを使って値や関数を、送ったり受け取ったりすることが出来ます。「Port:JSとやり取りする」のページで解説しています。

-- Elmに入ってくる値
port prices : (Float -> msg) -> Sub msg

-- Elmから出て行く値
port time : Float -> Cmd msg
var app = Elm.Example.worker();

app.ports.prices.send(42);               //JsからElmへ送る。
app.ports.time.subscribe(callback);      //ElmからJsへ来るので受け取る。
app.ports.time.unsubscribe(callback);

results matching ""

    No results matching ""