はじめに
少し前に流行った湯婆婆に便乗してみました。ついでに2年前に入門すると言って何もやらなかったElmで書いてみようと思いました。
まずは完成品
実装をする
今回の要件は、入力された文字列から1文字を選択してそれを出力することですね。というわけでElmっぽくmodel
とupdate
とview
を考えてみます。
model
まず必要と考えたのは、**贅沢な名前(入力した名前)**ですね。これはluxuriousName
として、あとはhidden
を使って「今からお前の名前は(ry」の表示を切り替えるためのhideNewName
を用意します。
type alias Model =
{ luxuriousName : String, hideNewName : Bool, positionOfName : Int }
init : ( Model, Cmd Msg )
init =
( { luxuriousName = "", hideNewName = True, positionOfName = 0 }, Cmd.none )
あと本当は用意するつもりはなかったpositionOfName
ですが、これはluxuriousName
からランダムに選んだ文字の位置になります。Elmの乱数ライブラリを使う関係で用意したものです。これについてはupdate
のところで触れたいと思います。
update
Elm初心者なので、もしかしたら突っ込みどころのある実装かもしれませんがこんな感じに書きました。ChangeName
はHtmlのinput
要素から入力された文字で、Send
はbutton
が押されたかどうかのメッセージです。
type Msg
= ChangeName String
| Send
| YubabaSelect Int
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ChangeName inputName ->
( { model | luxuriousName = inputName }, Cmd.none )
Send ->
( { model | hideNewName = False }, Random.generate YubabaSelect (Random.int 0 (String.length model.luxuriousName - 1)) )
YubabaSelect randomValue ->
( { model | positionOfName = randomValue }, Cmd.none )
ここでYubabaSelect
という適当なメッセージを定義しました。最初は乱数生成はrondom 0 N
のような形で実現すると考えていたのですが、この記事をみる感じそんな単純に実装できないことがわかったので、用意したものです。このメッセージは、最初にSend
というメッセージを受け取った時に
Random.generate YubabaSelect (Random.int 0 (String.length model.luxuriousName - 1))
が実行されてその結果がYubabaSelect randomValue
という形で受け取ります。また、任意の1文字を抽出するという処理のためにelm-community/list-extraを使いました。
convertNewName : Int -> String -> String
convertNewName index oldName =
Maybe.withDefault "" (List.Extra.getAt index (String.split "" oldName))
一旦String
をList String
に変換します。List.Extra.getAt
を使ってpositionOfName
の位置の文字を取り出せば1文字の抽出ができるのですが、~~このString
はMaybe String
になるのでNothing
だった場合の処理をしました。~~←Maybe
の処理方法は、@ababup1192さんの指摘によりMaybe.withDefault
を使うことでcase of
を書くことなく処理ができました。
view
あとは何も考えずにview
を書きます。
view : Model -> Html Msg
view model =
div []
[ div [] [ text "契約書だよ。そこに名前を書きな。" ]
, div []
[ span []
[ input [ class "input", placeholder "名前", value model.luxuriousName, onInput ChangeName ] []
, button [ onClick Send ] [ text "書いた" ]
]
]
, div [ hidden model.hideNewName ]
[ text
("フン。"
++ model.luxuriousName
++ "というのかい。贅沢な名だねぇ。"
)
]
, div [ hidden model.hideNewName ]
[ text
("今からお前の名前は"
++ convertNewName model.positionOfName model.luxuriousName
++ "だ。いいかい、"
++ convertNewName model.positionOfName model.luxuriousName
++ "だよ。分かったら返事をするんだ、"
++ convertNewName model.positionOfName model.luxuriousName
++ "!!"
)
]
]
これで湯婆婆変換された名前が表示されるフォームが実装できました!!
さいごに
ElmでList操作をすることや乱数を使うことが思ったより簡単ではなかったのですが、とりあえず書くことはできました。しかし慣例だと未入力の時のException
表示をするみたいですが、Elmでやるのはちょっと難しそうな気がしたので断念しました。。。
自分でElmアプリを書いたのはこれが初めてなので指摘あればコメントくださると嬉しいです。