さばとたんと遊ぼうIndex

6.さばとと関数

sabato_icon_1.png

テストドライブの結果はどうだったかの?

so_icon.png

当たり前やけどなんも無かったで?性能も今までのBasic.txtと同じやな。

sabato_icon_1.png

!?もしやアレだけやって性能は変わっておらんのか?

so_icon.png

当然やがな。今までKeyでやっとったことをLuaに移しただけやから。

sabato_icon_1.png

あれだけやってそんなものかの。Luaらしいことはいつになればできるんじゃ?

so_icon.png

Luaらしい言うたら_Gとかやなぁ。今回の関数と次のテーブル押さえれば何とかなるはずやで。

sabato_icon_1.png

Gじゃと?不吉な名前を口にするでない。

so_icon.png

黒いアレとは別物や。_がついとる。まぁ詳しいことは次回説明するとして、今回は関数やな。

sabato_icon_1.png

関数とな?前やった変数とはどう違うのじゃ? 鯖「どう違うゆうて・・ほとんど同じところあらへんがな。

sabato_icon_1.png

むぅ、それなら紛らわしい名前をつけるでない。

so_icon.png

日本語やから紛らわしいんやって。英語やったら『variable』と『function』やから何の問題もあらへん。

sabato_icon_1.png

主はそうまでして妾に英語を使わせたいのか?

so_icon.png

いや別に日本語のままでええで?それより関数の解説や解説。実は神さんももう関数使うてるで?

sabato_icon_1.png

すでに使っておるとな?

so_icon.png

毎度おなじみの『out』とか『_KEY』とかがそうやな。

sabato_icon_1.png

ふむ、ならば使っているというのはout(0, "さばとたんかわいいよさばとたん")とかのことかの?

so_icon.png

ご名答や。ここからはいくつか今までにない用語の説明はいるからしっかり聴いとってくらはいな。

so_icon.png

まず、out(・・・・)の形が『関数呼び出し』や。英語やと『function call』やな、エラーで出てくることアルから覚えとって損はないで。

sabato_icon_1.png

いつぞみたattempt to call a nil valueのcallはもしかしてこれかの?

so_icon.png

!?神さんの記憶力は不思議やな。callについてはその通りなんやけどそれ以上詳しいことは今日の授業が進んでから説明するわ。

so_icon.png

ほんで、次の用語は『引数(ひきすう)』や。out(0, "さばとたんかわいいよさばとたん")やと『0』と『"さばとたんかわいいよさばとたん"』がこれやな。関数呼び出しのときに関数に渡す情報やな。『,』で区切っていくつでも書いていける。

sabato_icon_1.png

ヒキスウか、なんか気持ちの悪い読み方じゃの。関数に情報を渡すというとどこに表示するかとかなにを表示するかとかそう言うことじゃな。

so_icon.png

そやな。次は例に_KEY(4)を使うで。この場合、_KEYの関数呼び出しで、引数は4や。ところが、こいつの場合は_KEY(4)自体が計算の中とかで数字みたいに振るまっとる。

sabato_icon_1.png

昨日も散々漬かったの。0と1が切り替わるんじゃったな。

so_icon.png

この場合の_KEY(4)が意味してる0とか1とかの数字を『返り値』というんや。因みにoutの場合は返り値はnilやから使えへんな。

sabato_icon_1.png

返り血とな。あれはレインコートとかビニールのジャンパーとかで防ぐとよいぞ。まぁ妾には関係のないことじゃが。

so_icon.png

とりあえずそれは変換が間違っとるで。ボケとらんで返り値のことはええか? さばと「関数呼び出しを数字として使うときの値のことじゃな。理解したぞ。

so_icon.png

ほなここで関数を1つ作ってみましょか。例によって例のごとくしたのやつを打ち込んでくださいな

 VAL{}KEY{}BODY{CORE(){} }
 Lua
 {
 function OnFrame()
 	out(0, add(1, 2));
 end
 function add(a, b)
 	return a + b;
 end
 }
sabato_icon_1.png

今日はまたずいぶんとシンプルじゃな。この様子だとfunction add〜endが関数をつくっとるのかの?

so_icon.png

それやけどまた細かい説明や。『function 作りたい関数の名前(引数の名前1,引数の名前2・・・・) 関数の中身 end』これで関数が作れる。

sabato_icon_1.png

引数の名前というのはなんじゃ?この場合だとa,bのようじゃが、さっきの引数の説明の時には出てこなかったぞ?

so_icon.png

先ほど話ましたんは関数を呼び出すときの話や。関数の中で引数として渡された情報を使うときには、1つ1つ名前つけなどれがどれかわからんやろ。

sabato_icon_1.png

それで引数に名前がつくのじゃな。これは呼び出すときに書いた順番と対応するのかの?

so_icon.png

そうやな。上でadd(1,2)とやってよびだしとるから、addの最初の行でa=1,b=2としとると思えばええわ。

sabato_icon_1.png

して、次のreturnはなんじゃろうか。『戻る』のだろうがどこへじゃ?

so_icon.png

あえてどこに戻るかいうたら関数を呼び出したところへやけど、それと同時にこれで返り値を設定できるんや。この場合やったら二つの引数を足した値を返り値にしとる。あと、どこにもreturnがないとその関数の返り値はnilになるで。

sabato_icon_1.png

ということはadd(1,2)の値は1+2=3ということじゃな。おお、確かに3が表示されておる。ところでこれ、outを呼び出しとるなかでまたaddを呼び出しとるがこれは問題ないのじゃな

so_icon.png

渡そうとしてる引数の中に又関数呼び出しがあったら、内側の関数呼び出しから順に処理して行くから大丈夫や。

sabato_icon_1.png

なるほど、よくできておるの。しかし足し算ぐらい別に関数を使わんでもよかろう?わざわざややこしくするメリットはどこにあるのじゃ?

so_icon.png

これくらいの例やとわかり辛いのは確かや。けどな、何度も出てくる同じ処理をまとめると便利なんや。昨日の例で言うと『ある変数が限界を超えないようにする』って3回くらいやったやろ?

sabato_icon_1.png

ENGINEとHANDLEとHBRAKEじゃな。確かにどれもおなじようなif文じゃったな。

so_icon.png

そこで、や。それを関数にまとめてしまうんや。こんな感じやな。これは昨日のBasic.txtに書いてくださいな

 function limit_value(val, min, max)
 	if val < min then
 		return min;
 	elseif val > max then
 		return max;
 	else
 		return val;
 	end
 end
sabato_icon_1.png

こんなかんじかの。

 Lua
 {
 function OnFrame()
 	if _KEY(0) > 0 then
 		ENGINE = ENGINE - 500;
 	elseif _KEY(1) > 0 then
 		ENGINE = ENGINE + 500
 	else
 		ENGINE = 0;
 	end
 	
 	if ENGINE > 2500 then
 		ENGINE = 2500;
 	elseif ENGINE < -2500 then
 		ENGINE = 2500;
 	end
 	HANDLE = HANDLE + (_KEY(2)-_KEY(3)) * -0.5;
 	if _KEY(2) == 0 and _KEY(3) == 0 then
 		if HANDLE >= 5 then
 			HANDLE = HANDLE - 5;
 		elseif 5 > HANDLE and HANDLE > 0 then
 			HANDLE = 0;
 		elseif 0 > HANDLE and HANDLE > -5 then
 			HANDLE = 0;
 		elseif -5 >= HANDLE then
 			HANDLE = HANDLE + 5;
 		end
 	end
 	if HANDLE > 20 then
 		HANDLE = 20;
 	elseif HANDLE < -20 then
 		HANDLE = -20;
 	end
 	BRAKE = _KEY(7) * 30;
 	HBRAKE = _KEY(7)*20 + _KEY(8)*20;
 	if HBRAKE > 20 then
 		HBRAKE = 20;
 	end
 end
 
 function limit_value(val, min, max)
 	if val < min then
 		return min;
 	elseif val > max then
 		return max;
 	else
 		return val;
 	end
 end
 }
so_icon.png

OKや。そしたら同じ処理の部分をlimit_valueつこうて書きかえるで。

 Lua
 {
 function OnFrame()
 	if _KEY(0) > 0 then
 		ENGINE = ENGINE - 500;
 	elseif _KEY(1) > 0 then
 		ENGINE = ENGINE + 500
 	else
 		ENGINE = 0;
 	end
 	
 	ENGINE = limit_value(ENGINE, -2500, 2500);
 	HANDLE = HANDLE + (_KEY(2)-_KEY(3)) * -0.5;
 	if _KEY(2) == 0 and _KEY(3) == 0 then
 		if HANDLE >= 5 then
 			HANDLE = HANDLE - 5;
 		elseif 5 > HANDLE and HANDLE > 0 then
 			HANDLE = 0;
 		elseif 0 > HANDLE and HANDLE > -5 then
 			HANDLE = 0;
 		elseif -5 >= HANDLE then
 			HANDLE = HANDLE + 5;
 		end
 	end
 	HANDLE = limit_value(HANDLE, -20, 20);
 	BRAKE = _KEY(7) * 30;
 	HBRAKE = _KEY(7)*20 + _KEY(8)*20;
 	HBRAKE = limit_value(HBRAKE, 0, 20);
 end
 
 function limit_value(val, min, max)
 	if val < min then
 		return min;
 	elseif val > max then
 		return max;
 	else
 		return val;
 	end
 end
 }
sabato_icon_1.png

一応主のいう通りに書き変えてはみたが何故これでENGINEやらなんやらが制限できるのじゃ?なにやら暴走しそうじゃからテストは主に頼むぞ。

so_icon.png

走りに行かせる前に仕組みを考えてくださいな。1つやれば他は同じことやからENGINE = limit_value(ENGINE, -2500, 2500);だけやるで。これがENGINEにlimit_valueの返り値を代入する式なんはええか?

sabato_icon_1.png

それくらいはわかっておる。問題はlimit_valueがどうなっとるかじゃ。

so_icon.png

ほなlimit_valueが呼び出されるとどうなるか見ましょか。まずENGINE,-2500,2500の3つの引数がそれぞれval, min, maxって変数にはいるな?

sabato_icon_1.png

渡された引数は関数を作るときに書いた順番どおりに名前がつけられるんじゃったな。

so_icon.png

さて、ここでval、つまりENGINEがmin、つまり-2500より小さかったらどないなる?

sabato_icon_1.png

最初のif文が条件を満たすの。そうするとreturn minになっとるの。

so_icon.png

はっきりと言うてなかったんは某のミスやけど、return なにかを実行するとそこで関数は終わりや。後どれだけ関数の中身が続いとっても関数を呼び出したところにもどってまう。

sabato_icon_1.png

するとここでreturn minじゃから、limit_valueの値は-2500となるの。すると、ENGINEは-2500じゃな。確かにENGINEが-2500より小さいと-2500になっとるの。

so_icon.png

2500より大きい場合も同じやな。elseifのところの条件に引っかかって2500になってまう。ほんで、-2500〜2500のときだけelseになるからreturn valちゅーことでそのままの値が返り値になるんや。

sabato_icon_1.png

確かによくできておるが、これではダメかの?いちいち返り値を使わずともこうやって代入すればいいはずじゃ。

 function limit_value(val, min, max)
 	if val < min then
 		val = min
 	elseif val > max then
 		val = max
 	else
 		val = val;
 	end
 end
so_icon.png

よーあるミスやけどそれは無理や。関数呼び出しのときに同じ値が代入されるだけであってvalとENGINEは別もんやから、valになんぼ代入してもENGINEの値は変わらんのや。

sabato_icon_1.png

ということは引数に渡したら勝手に値が変わってしまう心配はしなくていいのじゃな。

so_icon.png

まぁ例外はあるけどな。そっちは明日やるとして神さんのいう通り基本的には引数で渡す分には勝手に変わる心配はあらへんな。

sabato_icon_1.png

難しいの、この間から妾のないすなアイディアがどうもうまく行かぬ。

sabato_icon_1.png

ところで、すごくきになるんじゃが、function OnFrame() というのはこの関数の作り方と同じように見えるのじゃが?

so_icon.png

ええとこに気づきはったな。神さんの気づいた通り、OnFrameっちゅー関数をつくっとるんや。

sabato_icon_1.png

ふむ、それならどこから呼び出しとるのじゃ?OnFrameの中身が実行されているように見えるが。

so_icon.png

どこから、というとRigidChips本体からやな。RigidChipsの本体がOnFrameをずっと繰り返し繰り返し呼び出しとるんや。

sabato_icon_1.png

さて、2回目くらいの講座のときに、後で説明してくれると言っておったattempt to call a nil valueの件はどうなのじゃ?これと関係がありそうじゃが。

so_icon.png

アレが出る理由はずばりOnFrameがないからや。OnFrameをつくっとらんと、RigidChips本体がなんぼOnFrameを呼び出そうとしても値がない(=nil)やから、nilを呼び出そうとした言うことであのエラーが出るんや。

sabato_icon_1.png

それじゃったら、まったく関係のないところでつくってもいない関数を呼び出してもでるのかの

 VAL{}KEY{}BODY{CORE(){} }
 Lua{
 function OnFrame()
 	out(0, sabato(1, 2));
 end
 function add(a, b)
 	return a + b;
 end
 }
sabato_icon_1.png

うむ、見事にエラーが出たの。

so_icon.png

自分でLua組んどってattempt to call a nil value〜が出たときはまずは関数名のうち間違いとかを見直してみるべきやな。

sabato_icon_1.png

今日もずいぶんと進んだの。やったことをまとめるとこんな感じじゃな。

	関数を使うのが"関数呼び出し"、そのとき渡す情報が"引数"。
	式の中で関数呼び出しを値として使うときの値が関数の"返り値"
	"function 関数名(引数名1,引数名2,...)〜end"で関数が作れる。
	返り値は関数の中で"return 値"の形で設定できる。
	但しreturnを通ると関数の実行はそこで終わり。
	なにも設定しないと返り値はnil
	
so_icon.png

神さんグッジョブや。次回はちょっと予定を変更してRCの関数の説明でもヤロカ。

前:さばととモデル:次:さばとといろんな関数


トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2021-05-16 (日) 21:52:13