追記
この記事は古いです。過去のものです。忘れてください
はじめに
この記事はElm Advent Calendar13日目の記事です
わかること
ElmのSignal.Mailboxが何者なのか分かる。
公式ドキュメントに書かれている内容とコードを読んで分かったことが書いてある。
わからないこと
Nativeモジュール(javascriptで書かれた部分)の中身。読んでません。
version
{
"elm-lang/core": "3.0.0"
}
MailBox
ざっくりいうと
ドキュメントにはまさにMailbox!みたいなことが書いてあります(確か)
Address(住所)にメッセージ(値)を送ると、Mailbox(郵便箱)を持っている人が受け取って見ることができます。
まさにMailbox!
ただメッセージを送る、というお仕事は副作用なので明示的にportなどを使って送らねばなりません。
やってみましょう。Try Elmに貼ればそのまま実行できます。
import Graphics.Element exposing (..)
import Task exposing (Task)
main = Signal.map show mailbox.signal
mailbox = Signal.mailbox "最初のメッセージ"
port post : Task.Task x ()
port post = Signal.send mailbox.address "次のメッセージ"
実行してみると、一瞬「最初のメッセージ」が実行された後「次のメッセージ」が表示されます
Mailboxを作るにはSignal.mailbox関数を使います。引数には初期値を与えています。この初期値が最初に画面に表示されています。
値はmailbox.signalで取り出せますが、名前からわかる通りSignal a型の値です。mailbox.addressに値を送ると値が変わるSignalですね
送り方は、手動で送る場合Signal.sendを使ってTaskにしてportを使って送ることです。
portを付けられたTaskは実行されます。sendで作られるTaskは与えられたaddressにメッセージを送ります
上の例では自分でportを使ってメッセージを送っていますが、The Elm ArchitectureなどではHtml.EventsのonClick関数にaddressとメッセージを与えてクリックされたらメッセージが送られるようになっています。
ここら辺の動きはNativモジュール内で定義されているので気になったら追ってみるといいかもしれません。
Mailboxに関してその他
関連する関数として、Signal.messageとSignal.forwardToがあります。
Signal.messageはGraphics.Inputで使われています。一方、elm-htmlではaddressが使われています。使い方的にはほぼ一緒に見えるのでなんで違うのかはよくわかりません。
Signal.forwardToは転送用のアドレスを作る関数です。先ほどのAddressはStringを送れましたが、送る時に値を変換したりしてStringにしてから送りたい場合に使えます。
mailbox :Maybe String
に送りたいときに、send mailbox.address (Just "メッセージ")
とやるのではなくStringを直接送れるstringAddress = Signal.forwardTo mailbox.address Just
を作ってから、send stringAddress "メッセージ"
で送れるようになります。
まとめ
MailboxはまさにMailbox!