を更に改造するぞい
こんな事を教えてもらった
あとカウンターの例で固定の数字ではなく、任意の数値増やしたいと言う場合は、
— ABAB↑↓BA (@ababupdownba) 2020年8月19日
type Msg = IncrementN Int
-- view
onClick (IncrementN 3)
-- update
lncrementN n -> …
こんな感じで扱えます
ABAB↑↓BA先生いつもありがとうございます
満へぇなので金の脳を贈ります
実際にやってみた
こちらが確認のVTRです(八嶋智人)
ellie-app.com
やったこと
Msgのアクションを一つに
- = Increment - | Decrement - | IncrementDouble - | DecrementDouble + = IncrementN Int
正負両方の任意の値を受けるアクションにした
updateのパターンマッチも修正
- Increment -> - { model | count = model.count + 1 } - - Decrement -> - { model | count = model.count - 1 } - - IncrementDouble -> - { model | count = model.count + 2 } - - DecrementDouble -> - { model | count = model.count - 2 } + IncrementN n -> + { model | count = model.count + n }
引数を受けるようにした
Doulble, Triple...
と増え続ける地獄を回避できた
viewのonClickも修正
- [ button [ onClick Increment ] [ text "+1" ] - , button [ onClick IncrementDouble ] [ text "+2" ] - , button [ onClick Decrement ] [ text "-1" ] - , button [ onClick DecrementDouble ] [ text "-2" ] + [ button [ onClick (IncrementN 1) ] [ text "+1" ] + , button [ onClick (IncrementN -1) ] [ text "-1" ]
引数を渡せるようにした
ここでミスをして一度エラーになっていた
+ [ button [ onClick IncrementN 1 ] [ text "+1" ] + , button [ onClick IncrementN -1 ] [ text "-1" ]
見ておわかりの通りIncrement n
だから引数渡すだけ
と愚直に追加していたのである
その結果以下のエラーだった
Too Many Args Line 33, Column 20 The `onClick` function expects 1 argument, but it got 2 instead. 33| , button [ onClick IncrementN -1 ] [ text "-1" ] ^^^^^^^ Are there any missing commas? Or missing parentheses? Too Many Args Line 31, Column 20 The `onClick` function expects 1 argument, but it got 2 instead. 31| [ button [ onClick IncrementN 1 ] [ text "+1" ] ^^^^^^^ Are there any missing commas? Or missing parentheses?
意訳
そこのお前!onClickが期待してる引数は1つだぜ!
親切すぎるエラーである
ここで「()
で囲むんだった」とABAB↑↓BA先生のコードを思い出し解決
java
だとわかるけどわからないエラーを吐き出して死んでいる所だが
Elm
は親切に
- 引数多いよ!
- ここだよ!ここ!
- もしかして
,
か()
忘れてない?
と波線までつけて教えてくれた
優しすぎるコンパイラである、きっと中にガンジーが入っているのだろう
ラブアンドピース!平和が一番!
完成…と見せかけて
ここまでだとコンパイラが親切で優しいだけのjavascript
と変わらないのである
そこでこちらの教えを実践する
任意の値のサンプルは注意点もあって Intのように広い範囲が必要がないときはむやみやたらに使うべきではありません
— ABAB↑↓BA (@ababupdownba) 2020年8月20日
これはhttps://t.co/E5DP64j4xK
このページを見るとよくわかるかなと思います
(自分のツイート貼るの恥ずかしい)>void型が存在してるせいなんですよね
— 🐊すがわに🐊 (@nek0roll) 2020年8月20日
なるほど…そのような理由が根底にあったのですね、ありがとうございます
型については可能なかぎり厳密にするべき、でしょうか?
今回のケースだと+1or+2のみなので、1と2のみの型を作るイメージです
参考ページについても目を通させて頂きます
> 型については可能なかぎり厳密にするべき、でしょうか?
— ABAB↑↓BA (@ababupdownba) 2020年8月20日
ですね case並べれるなら並べるようにしてます
Int
だと広すぎるのでより厳密にする
やりたいこと
Int
だと広すぎる(-2147483647~2147483647)
Basics - core 1.0.5-2, -1, 1, 2
のみを許容する型にしたい
その1 カスタム型を作成してみる
-2~2を定義したカスタム型を作成
type IncrementNInt= PlusOne | PlusTwo | MinusOne | MinusTwo
PlusOne, PlusTwo
とかはVariant
(バリアント)っていうらしい
Msg型の引数の型を変更
- = IncrementN Int + = IncrementN IncrementNInt
さっき作ったカスタム型に変更する
これでIncrementN
は定義4つのVariant
以外受け入れない引数になった
パターンマッチを型に合わせて変更
- { model | count = model.count + n } + case n of + PlusOne -> + { model | count = model.count + 1 } + PlusTwo -> + { model | count = model.count + 2 } + MinusOne -> + { model | count = model.count - 1 } + MinusTwo -> + { model | count = model.count - 2 }
viewを変更
- [ button [ onClick (IncrementN 1) ] [ text "+1" ] - , button [ onClick (IncrementN -1) ] [ text "-1" ] + [ button [ onClick (IncrementN PlusOne) ] [ text "+1" ] + , button [ onClick (IncrementN PlusTwo) ] [ text "+2" ] + , button [ onClick (IncrementN MinusOne) ] [ text "-1" ] + , button [ onClick (IncrementN MinusTwo) ] [ text "-2" ]
直接数値を定義するのではなく、用意したVariant
を渡すようにした
動いた
エラーが起きるか色々試す
+3を追加しちゃう
+ , button [ onClick (IncrementN 3) ] [ text "+3" ]
怒られた
Type Mismatch Line 44, Column 40 The 1st argument to `IncrementN` is not what I expect: 44| , button [ onClick (IncrementN 3) ] [ text "+3" ] ^ This argument is a number of type: number But `IncrementN` needs the 1st argument to be: IncrementN Hint: Only Int and Float values work as numbers.
意訳
IncrementNの第一引数にnumber渡してるけど IncrementNの第一引数はIncrementNInt型やぞ
エラー吐いてえらい!(コウペンちゃん)
存在しないVariant
を追加しちゃう
+ , button [ onClick (IncrementN PlusThree) ] [ text "+3" ]
怒られた
Naming Error Line 44, Column 40 I cannot find a `PlusThree` variant: 44| , button [ onClick (IncrementN PlusThree) ] [ text "+3" ] ^^^^^^^^^ These names seem close though: PlusOne PlusTwo Just True Hint: Read <https://elm-lang.org/0.19.1/imports> to see how `import` declarations work in Elm.
意訳
そんなVariantねンだわ PlusOne, PlusTwoってやつが近いけどもしかしてこれにしたかった?
親切すぎる
git checkotu
って書いた時に
git: 'checkotu' is not a git command. See 'git --help'. The most similar command is checkout
って言ってくれるより親切
その2 パターンマッチで数値を絞る
Msgは特にいじらず
type Msg = IncrementN Int
パターンマッチにそのまま追加
+ 1 -> + { model | count = model.count + n } + 2 -> + { model | count = model.count + n } + -1 -> + { model | count = model.count + n } + -2 -> + { model | count = model.count + n } + _ -> + { model | count = model.count + 0 }
intのパターンマッチで、-2~2以外は未使用なので
_
のワイルドカードを定義した
viewは既存に+2,-2を追加
+ , button [ onClick (IncrementN 2) ] [ text "+2" ] + , button [ onClick (IncrementN -2) ] [ text "-2" ]
死んだ
Unexpected Symbol Line 30, Column 17 I ran into an unexpected symbol: 30| -1 -> ^ I was not expecting to see a - here. Try deleting it? Maybe I can give a better hint from there?
意訳
なんか急に`-`出てきたんだけどなにこれ? これミスなら削除してくれ
順番変えてみた
-1 -> { model | count = model.count + n } -2 -> { model | count = model.count + n } 1 -> { model | count = model.count + n } 2 -> { model | count = model.count + n } _ -> { model | count = model.count + 0 }
マイナスを先頭にした
死んだ
Unexpected Symbol Line 26, Column 17 I ran into a minus sign unexpectedly in this pattern: 26| -1 -> ^ It is not possible to pattern match on negative numbers at this time. Try using an `if` expression for that sort of thing for now.
意訳
今の所パターンマッチでマイナス使えねンだわ if使ってくれや
一応調べてみたらこんなんありました github.com
I've bumped into this as well, trying to decode a JSON payload where -1 is used as a flag. But practical examples aside, it just seems odd in principle that the language will allow you to pattern match against integers, unless those integers happen to be negative.
意訳(間違ってたらごめんちゃい)
再現した、そもそも整数パターンマッチってどうなの?
(ElmならVariat使ってね。ってことかな)
if
使えば実現出来るのかも知れないけど、issue上でこんな意見もあるし
そもそもやろうとしていることが間違っているのかも知れない
まとめ
- 引数をカスタム型にしてパターンマッチしたら行けた
- 型作って厳密にするとヒューマンエラーなくなるので嬉しい
- intで受けつつ、値を絞るイメージが合ったけど間違い?
PHPだけどこういうコードのイメージ
<?php const ALLOW_NUMBERS = [-2, -1, 1, 2]; public function incrementN(int $count, int $n) { if (!in_array($n, self::ALLOW_NUMBERS, true) { return; } return $count + n; }