如何在简单的应用程序中“生成”自己的命令

时间:2017-05-25 08:18:59

标签: elm

作为榆树的学习范例,我想用榆树建筑创造一个简单的蛇游戏。

到目前为止,这是完整的代码: https://gist.github.com/DanEEStar/b11509514d72eaafb640378fc7c93b44

程序的一部分是UpdateWorld消息,它通过按钮单击和updateWorld函数生成,该函数在用户按空格键时调用。

这导致以下编译和工作代码(代码片段形成完整代码):

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        UpdateWorld ->
            ( updateWorld model, Cmd.none )

        KeyPress keyCode ->
            ( handleInput keyCode model, Cmd.none )


handleInput : Int -> Model -> Model
handleInput keyCode model =
    case Char.fromCode keyCode of
        ' ' ->
            updateWorld model

        _ ->
            model


updateWorld : Model -> Model
updateWorld model =
    { model | snake = updateSnake model.snake }


subscriptions : Model -> Sub Msg
subscriptions model =
    Keyboard.presses KeyPress


view : Model -> Html Msg
view model =
    div []
        -- here I can simply tell `onClick` to generate the `UpdateWorld` command
        [ button [ onClick UpdateWorld ] [ text "tick" ]
        ]

在此代码段中,很明显onClick事件会生成UpdateWorld命令。 但是在handleInput函数中,我必须“手动”调用updateWorld函数。

我宁愿做的是从我的UpdateWorld函数“生成”一个新的handleInput命令。我认为这将澄清代码。类似的东西:

handleInput keyCode =
    case Char.fromCode keyCode of
        ' ' ->
            -- how can I generate this command in my code
            UpdateWorld

我怎么能这样做?

这是一个好主意,还是一个更好的模式?

1 个答案:

答案 0 :(得分:4)

回想一下update只是一个函数,这意味着你可以递归地调用它。

考虑更改handleInput的签名以返回(Model, Cmd Msg),就像update函数一样:

handleInput : Int -> Model -> (Model, Cmd Msg)
handleInput keyCode model =
    case Char.fromCode keyCode of
        ' ' ->
            update UpdateWorld model
        'a' ->
            { model | snake = changeSnakeDirection model.snake West } ! []
        ...

您可以删除updateWorld函数并将该代码移动到UpdateWorld消息处理程序:

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        UpdateWorld ->
            ( { model | snake = updateSnake model.snake }, Cmd.none )

        ChangeDirection newDirection ->
            ( { model | snake = changeSnakeDirection model.snake newDirection }, Cmd.none )

        KeyPress keyCode ->
            handleInput keyCode model