次回作もよろしくやで!
→**Array.mapが分からないからArray.mapもどきを作ってみた**
その1: constが使われていない
ワイ「さあ、今日はこのショッピングサイトのJSを修正するで」
ワイ「どれどれ、コードはどんな感じかいな」
let totalPrice = getTotalPrice() - point;
ワイ「ふむふむ」
ワイ「このpointいう変数が関係ありそうやけど、このpointには何が入ってんのかいな」
ワイ「ええっと、pointを定義しとる部分は」
let point = 300;
ワイ「↑ここやな」
ワイ「pointには300が入っとるんか」
ワイ「でも・・・」
let point = 300;
/* ----------- */
/* 約300行の処理 */
/* ----------- */
let totalPrice = getTotalPrice() - point;
ワイ「pointを定義した後に300行ほどのコードが挟まっとるから」
ワイ「途中でpointの値が上書きされて変わっとるかもしれへんな」
ワイ「いまpointはどんな値を参照してんねやろ・・・」
ワイ「しゃあない、途中のコード全部追ってくか・・・」
〜2時間後〜
ワイ「け、結局どこでも再代入してないんかい」
ワイ「ほなconstにしとかんかい!!!」
ワイ「constなら再代入されへん事が保証されとるからな」
ワイ「間の300行のコードを読まんでもええわけや」
教訓
-
varやletより、できるだけconstを使うように気をつけよう - でも
constを使っていてもオブジェクトのプロパティは変更できてしまうので気をつけよう
ハスケル子「Elmならデフォルトで再代入できないので、気をつける必要すらないですよ」
ハスケル子「そもそも再代入という概念がないので」
point = 300
ハスケル子「これだけです」
ハスケル子「varもletもconstもないです」
ハスケル子「代入というより定義です」
ハスケル子「JSでいうオブジェクトみたいなのは、Elmではレコードっていうんですけど」
ハスケル子「Elmではレコードも不変です」
ハスケル子「今このプロパティ1はどんな値を参照してたっけ・・・?」
ハスケル子「っていうことがありません」
ワイ「お、おう・・・」
ハスケル子「ていうか途中の処理を300行ぜんぶ読まなくても」
ハスケル子「pointの中身をconsole.log()で確認すればよかったんじゃないですか?」
ワイ「それが、最近**konsooru.Rogu()**の調子が悪くて」
ワイ「エッラーばっかり吐くねん」
社長「(そんだけタイポしてりゃな・・・)」
ハスケル子「(あとエッラーって何)」
ハスケル子「(唯一神・・・?)」
その2: JSDocと実装が違う
ワイ「次はこの関数を修正しよか」
ワイ「ん、なんか関数の上にコメントが書いてあるで」
/**
* @param {Number} price
* @return {Number}
*/
function displayUserName (userId) {
/* 〜処理内容〜 */
}
ワイ「おお、関数の使い方についてのコメントか」
ワイ「JSDocいうやつやな」
ワイ「この関数は引数としてpriceという数値を受け取って、戻り値も数値ですよ、ってことやな」
ワイ「こういうコメントが書いてあると、修正する側としては大助かりや」
ワイ「ありがたいこっちゃな」
ワイ「・・・ありゃ?」
ワイ「実際に関数の中身を見てみたらJSDocと全然ちゃうやん!!!」
ワイ「どうやら他の関数のJSDocをコピペして、編集し忘れたっぽいで・・・」
ワイ「勘弁してや・・・」
ワイ「逆にトラップになってもうとるやん・・・」
教訓
- JSDocを書くのはええけど、間違えると逆にトラップ化
- コードだけ修正してJSDocが古いまま、というミスにも気をつけよう
ハスケル子「Elmなら型注釈がJSDocの代わりになりますよ」
displayUserName : Int -> String
displayUserName userId =
-- ここに処理内容
ハスケル子「こんな感じです」
ハスケル子「型注釈で書いた通りに実装しないとコンパイルが通らないので」
ハスケル子「間違いないです」
ワイ「お、おう・・・」
その3: ユーザが変な値を入れると、変な表示になる
ワイ「なんやこの注文画面」
ワイ「数量を入力する部分にウンて入力してみたら」
ワイ「**数量: ウン個**って表示されとるやないかい」
ハスケル子「(なんで試したんだろう・・・)」
ワイ「ちゃんとバリデーションが効いてないくさいで」
ワイ「**ウン個**だけに」
ハスケル子「(何でそんなにつまんない事が思いつくんだろう・・・)」
ワイ「お客様が見る画面になんてモノを表示させてんねん」
社長「(いや、そのお客様、表示させに行ってるやん)」
教訓
- どんな値を入力しても変な表示にならないように、注意してブラウザテストしよう
ハスケル子「ElmならInt型の変数に文字列は入れられないので安心ですよ」
ワイ「でもユーザが文字列を入れて来たらどうすんの」
ハスケル子「Maybe型があるので、そういう不確実な値も事前に検査できます」
ワイ「ま、まじか・・・」
その4: 関数ネストし過ぎ
ワイ「なんやこれ・・・」
let displayName = suitCase(rareCase(camelCase(name)));
ワイ「関数が入れ子になり過ぎて可読性が・・・」
ワイ「でもこれは、しゃあないか・・・?」
let camelCasedName = camelCase(name);
let rareCasedName = rareCase(camelCasedName);
let suitCasedName = suitCase(rareCasedName);
ワイ「こんな感じに書き変えるのも冗長やしなあ・・・」
教訓
- 諦めよう
ハスケル子「Elmならパイプラインでこう書けますよ」
displayName =
name |> camelCase |> rareCase |> suitCase
ワイ「おお、なんと読みやすい・・・」
ワイ「でもJSにも**そのうち導入される可能性がある**らしいで?」
ハスケル子「いきなりパイプラインだけ導入しても」
ハスケル子「関数が**カリー化**されてないと」
ハスケル子「あんまり使い所ないですよ」
ハスケル子「あと、あらかじめパイプラインありきで」
ハスケル子「引数の順番を考えておかないと使えないです」
ワイ「そうなんか・・・」
でもさ・・・
ワイ「でも、そんな便利な言語だと、お値段もお高いんでしょう・・・?」
ハスケル子「実は・・・」
ハスケル子「なんと無料です!」
ワイ「ええぇっ!!!」
ハスケル子「しかもElmはコンパイルしてJavaScriptに変換できるんです」
ワイ「ま、まじか・・・」
まとめ
ワイ「ハスケル子ちゃん・・・」
ワイ「ワイも、もっと早くハスケル子ちゃんオススメのElmを勉強しとけばよかったわ・・・」
ワイ「人生の選択間違えたわ・・・」
ワイ「ああ・・・また心がダークモードになってきたで・・・」
ハスケル子「あんまり完璧で眩しい人より、ダークモードの方が目に優しいですよ」
ワイ「ハスケル子ちゃん・・・」
ワイ「でもなんか、ワイは人間関係とかでも」
ワイ「いつも選択を間違って後悔ばかりなんや・・・」
ハスケル子「逆に選択を間違えない人っているんですか?」
ハスケル子「いつも答えが分かってて選択してる人なんて、多分いませんよ」
ハスケル子「間違ってるかもしれない選択をし続けていく」
ハスケル子「それが人生ですよ」
ワイ「ハスケル子ちゃん・・・!」
ハスケル子「今日も、明日も、やめ太郎さんに出来ることをしましょう」
ワイ「ワイにできること・・・」
ワイ「それってなんやろか・・・」
ハスケル子「・・・」
ハスケル子「ちょっと思いつかないですけど」
ワイ「何もないんかい!!!」
〜おしまい〜
追記: ビギナーにお勧めのElm記事たち
Elmで体験する関数型言語の面白さ
VS Code で Elm の開発環境を構築する on Windows 10
値が制約を満たしていることを型で保証する
次回作もよろしくやで
→**Array.mapが分からないからArray.mapもどきを作ってみた**
-
Elmのレコードの場合は、プロパティでなく「フィールド」と呼びます。 ↩