カレーで小難しい話をしてみる(その3)
その2はこちら
息抜き回その31
カレー作りの続き。オリジナル言語を定義しつつプログラミングしてみる。
これまでの状況
最初に作った処理フローはこんな感じ。
ただただ長いから関連個所だけ抜粋。
graph TD 材料を用意する--> 鶏肉を一口大に切る--> 人参を一口大に切る--> 玉ねぎを一口大に切る--> じゃがいもを一口大に切る-->省略
前回は鶏肉を一旦飛ばして人参を切ろうとしてた
材料を切る
考えやすいように、人参1本のgと一口大にした時のgを以下に決める。
人参1本:150g,一口大1個:10g
人参の構造
人参{ 重さ; }
前回までの処理
人参.重さ = 150; 一口大の人参の数 = 0; この処理を繰り返す{ もし( 人参.重さ <= 10 )なら{ // もう切れないから切れ端も加えておしまい 一口大の人参の数 += 1; 切れ端の重さ = 人参.重さ; 繰り返しを抜ける; } // 一口大に切る 人参.重さ -= 10; 一口大の人参の数 += 1; } 切れた人参[一口大の人参の数]; カウンタ = 0; この処理を繰り返す{ もし( カウンタ >= 一口大の人参の数 )なら{ // 全部設定終わったから終了 繰り返しを抜ける; } // 一口大の人参の重さを設定 もし( カウンタ = (一口大の人参の数-1) )なら{ // カウンタは0始まりなので、最後の人参のカウンタ=(一口大の人参の数-1) 切れた人参[カウンタ].重さ = 切れ端の重さ; } そうじゃないなら{ 切れた人参[カウンタ].重さ = 10; } カウンタ++; }
配列だと数が決まってからじゃないと定義できないから、処理が冗長。。
ってことで、ベクター(Vector)的な概念を導入。
今はベクター=要素を後から追加できる配列。程度の概念で。
配列.追加(要素)
で末尾に新しい要素を追加できることにする。
あとは配列.要素数
で要素数取れることにする。
ベクターを踏まえて書き直し
人参.重さ = 150; 一口大の人参.重さ = 10; 切れた人参; この処理を繰り返す{ もし( 人参.重さ <= 一口大の人参.重さ )なら{ // もう切れないから切れ端も加えておしまい 余った人参.重さ = 人参.重さ; 切れた人参.追加(余った人参) 繰り返しを抜ける; } // 一口大に切る 人参.重さ -= 一口大の人参.重さ; 切れた人参.追加(一口大の人参) }
だいぶスッキリ。ついでに処理中に一口大の人参の重さ
を意識して書いてた10
ってのを一口大の人参.重さ
に置き換え。
もともと書いてた10
てのは、そのままだと何の数字か分からない、けど何かの効果(意味)があるマジックナンバー(魔法の数字)
と呼ばれるもので、メンテの邪魔2なので基本的に消してく3。
やっと人参が切れたので、同様に玉ねぎも切る。 玉ねぎの重さは↓で定義
玉ねぎ1個:200g,一口大1個:5g
玉ねぎの構造
玉ねぎ{ 重さ }
人参.重さ = 150; 一口大の人参.重さ = 10; 切れた人参; この処理を繰り返す{ もし( 人参.重さ <= 一口大の人参.重さ )なら{ // もう切れないから切れ端も加えておしまい 余った人参.重さ = 人参.重さ; 切れた人参.追加(余った人参) 繰り返しを抜ける; } // 一口大に切る 人参.重さ -= 一口大の人参.重さ; 切れた人参.追加(一口大の人参) } 玉ねぎ.重さ = 200; 一口大の玉ねぎ.重さ = 5; 切れた玉ねぎ; この処理を繰り返す{ もし( 玉ねぎ.重さ <= 一口大の玉ねぎ.重さ )なら{ // もう切れないから切れ端も加えておしまい 余った玉ねぎ.重さ = 玉ねぎ.重さ; 切れた玉ねぎ.追加(余った玉ねぎ) 繰り返しを抜ける; } // 一口大に切る 玉ねぎ.重さ -= 一口大の玉ねぎ.重さ; 切れた玉ねぎ.追加(一口大の玉ねぎ) }
人参の処理をコピペして、玉ねぎに変えただけ。
ただ、いちいちコピペするの面倒なので、関数の概念を導入。
対象を切る(対象物, 切り分ける重さ){ 切り分けた対象物.重さ = 切り分ける重さ; 切れた対象物; この処理を繰り返す{ もし( 対象物.重さ <= 切り分ける重さ )なら{ // もう切れないから切れ端も加えておしまい 余った対象物.重さ = 対象物.重さ; 対象物.追加(余った対象物) 繰り返しを抜ける; } // 指定された重さに切る 対象物.重さ -= 切り分ける重さ; 切れた対象物.追加(切り分けた対象物) } return 切れた対象物; }
関数は処理のまとまり。関数名(引数){処理内容}
で定義。
引数=関数の呼び出し元から、関数に渡したい値。複数渡したいときは,
で区切る。
return
は関数の実行結果はこれですよ。って呼び出し元に返す値。
いま作った関数を使って書き直し
人参.重さ = 150; 一口大の人参.重さ = 10; 切れた人参 = 対象を切る(人参, 一口大の人参.重さ); 玉ねぎ.重さ = 200; 一口大の玉ねぎ.重さ = 5; 切れた玉ねぎ = 対象を切る(玉ねぎ, 一口大の玉ねぎ.重さ);
すごくスッキリ。こんな感じでよく使いそうな処理は関数化しておくと、コードも見やすいし楽が出来る。
そういえば玉ねぎは2個必要だったので、2つにする
一口大の人参.重さ = 10; 人参.重さ = 150; 切れた人参 = 対象を切る(人参, 一口大の人参.重さ); 一口大の玉ねぎ.重さ = 5; 玉ねぎ1.重さ = 200; 切れた玉ねぎ1 = 対象を切る(玉ねぎ1, 一口大の玉ねぎ.重さ); 玉ねぎ2.重さ = 200; 切れた玉ねぎ2 = 対象を切る(玉ねぎ2, 一口大の玉ねぎ.重さ);
あとは残ってる鶏肉とじゃがいも。
じゃがいも1個:100g,一口大1個:20g 鶏肉一口大1個:20g
じゃがいも{ 重さ } 鶏肉{ 重さ }
一口大の鶏肉.重さ = 20; 鶏肉.重さ = 300; 切れた鶏肉 = 対象を切る(鶏肉, 一口大の鶏肉.重さ); 一口大の人参.重さ = 10; 人参.重さ = 150; 切れた人参 = 対象を切る(人参, 一口大の人参.重さ); 一口大の玉ねぎ.重さ = 5; 玉ねぎ1.重さ = 200; 切れた玉ねぎ1 = 対象を切る(玉ねぎ1, 一口大の玉ねぎ.重さ); 玉ねぎ2.重さ = 200; 切れた玉ねぎ2 = 対象を切る(玉ねぎ2, 一口大の玉ねぎ.重さ); 一口大のじゃがいも.重さ = 20; じゃがいも.重さ = 100; 切れたじゃがいも = 対象を切る(じゃがいも, 一口大のじゃがいも.重さ);
これで全部一口大に切れた。今日はここまで。
今日のまとめ
関数の概念を導入したから、次からは色々楽になるはず。
ただ、実は言語として欠陥ある状態で突き進んでるんだよね。どうしたものか。