だいぶ前にElm触ってゲーム作った時はElmに色々と不満があったんだけど、あれからElmもだいぶバージョンアップして0.15.1ではエラーが人フレンドリーになったらしい。前回の不満がどれだけ解決されているか調べてみよう。
関数の引数の数間違いが謎の型エラーになったりする
module Test where
import Html exposing (text)
message2: String -> String -> String
message2 world world2 = "Hello, " ++ world ++ " " ++ world2
main = text (message2 "World?" "World!")
というメッセージを表示するだけのコードを書いて、
main = text (message2 "World?")
と引数の数を間違うと、
The 1st argument to function `text` has an unexpected type.
8| text (message2 "World?")
^^^^^^^^^^^^^^^^^
As I infer the type of values flowing through your program, I see a conflict
between these two types:
String
String -> String
8行目のここの引数がString
で無くString -> String
だぞと出る。素晴らしい。抜群に分かりやすくなっとる。
レコードのアップデートと追加構文を間違った時のパーサーのエラーが謎だった
main関数を
main =
let
world = {str = "World??"}
world2 = {world | str2 = "World!!"}
in text (message2 world2.str world2.str2)
とし、
world2 = {world | str2 = "World!!", str3 = "World?!"}
と許可されていない複数のフィールド追加を行うと、
11| world2 = {world | str2 = "World!!", str3 = "World?!"}
^
I am looking for one of the following things:
a closing bracket '}'
an expression
an infix operator like (+)
whitespace
とちゃんとここで'}'を閉じろと言う。素晴らしい。
型の宣言でのエラーや変数名の重複でその行番号を教えてくれない
message2: String -> String -> String2
とすると
Cannot find type `String2`
5| message2: String -> String -> String2
^^^^^^^
Maybe you want one of the following?
String
こう。
world = {str = "World??"}
world = {world | str2 = "World!!"}
とすると
Naming multiple values `world` in a single let-expression makes
things ambiguous. When you say `world` which one do you want?
11| world = {world | str2 = "World!!"}
^^^^^
Find all the values named `world` in this let-expression and
do some renaming. Make sure the names are distinct!
こう。完璧ではないか。
乱数シードに現在時刻が欲しい
これはエラーメッセージとは関係ないのだが、乱数の初期化のために現在時刻が欲しかったのだが、その方法が良く分からなかった。
Elmの中だけでなんとかしようと思わないでportを使ってJavaScriptから供給すればいいらいいぞ。
portはElmとJavaScriptの間で値をやりとりする仕組みで、JavaScriptからsendされた値をElmのSignalとして受け取ることができる。
Elm.fullscreen(Elm.Test, {beginTime: Date.now()});
とJavaScriptからElmを起動する時に引数で与えた値を、
port beginTime: Float
main =
let
world = {str = toString beginTime}
とportを介してもらえば良い。portってSignalじゃなくてもいいのね。たぶん不変な値限定だけど。
requestAnimationFrame対応
ElmのPongの例とかだと画面の更新はSignal.map inSeconds (fps 35)
とか使っていてタイマーベースだけど、できればこれはrequestAnimationFrameにしたい。
それにはelm-animation-frameを使えば良い。elm package install jwmerrill/elm-animation-frame
でパッケージをインストールし、
main =
let
frameNumSignal = Signal.map toString
(Signal.foldp (+) beginTime AnimationFrame.frame)
messageSignal = Signal.map (message2 "World?!") frameNumSignal
in
Signal.map text messageSignal
のようにAnimationFrame.frameをトリガに画面を更新すれば良いらしいぞ。
Elmイケているではないか
バージョンアップで着実に欠点が埋められている感じ。portを使ったJavaScriptとの連携がうまく使えれば、ゲーム作りにもいいかも。あとは良いIDEが欲しいよな。