19
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Elmで湯婆婆を実装してみる

Last updated at Posted at 2020-11-19

はじめに

少し前に流行った湯婆婆に便乗してみました。ついでに2年前に入門すると言って何もやらなかったElmで書いてみようと思いました。

まずは完成品

スクリーンショット 2020-11-19 13.06.30.png

実装をする

今回の要件は、入力された文字列から1文字を選択してそれを出力することですね。というわけでElmっぽくmodelupdateviewを考えてみます。

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要素から入力された文字で、Sendbuttonが押されたかどうかのメッセージです。

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))

一旦StringList Stringに変換します。List.Extra.getAtを使ってpositionOfNameの位置の文字を取り出せば1文字の抽出ができるのですが、~~このStringMaybe 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アプリを書いたのはこれが初めてなので指摘あればコメントくださると嬉しいです。

19
9
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?