百億のマインクラフトと千億のタートル

つまり、マイクラワールド1つあたりタートルが10匹生息しているわけですね。

もし変数に何か入っているならば・・・え?無が入っているの?

はじめに

前回記事からしばらく時間がたちましたがいかがお過ごしでしょうか。

hevo2.hatenablog.com

前回紹介した「yuka3」プログラム活用してます?

シンプルで便利ですよね。10歩分の床ブロックを敷き詰めたい(往復で2列)なら、こう。

> yuka3 10

以下のように16歩分でも問題なし。ただしその分のブロック32個(= 16 × 2)をタートルに渡すの忘れないでくださいね。

> yuka3 16

でも、何度も使っているうちにこんなことやらかしませんでした?

> yuka3

f:id:hevohevo:20191004200407p:plain
エラーメッセージ「13行目:for文の終端値は数字でないといけません」

つまり、引数なしでこのプログラムを実行したら、「ソースコードの13行目:for文の終端値は数字でないといけません」とエラーメッセージが表示されたわけですね。

ちょっと13行目を確認しましょう。

for i=1,hosuu do

つまり、変数hosuuの値が数値ではないと。それは当たり前ですよね。6行目でlocal hosuu = ...のようにコマンドライン引数を変数hosuuに代入していますが、そもそも引数を入力してないので、その値を代入する変数hosuuの値が数値なわけがありません。

何も入ってないが入ってる

では何が変数hosuuに入っているのでしょうか。

結論から言うと何も入っていません。

いえ、正確に言うと「何もない」という情報がこの変数に入っています。

それをLua言語では「nil」(ニル)と呼びます。つまりLua言語では、「何もない(無)」をnilとして表現するわけですね。覚えておきましょう。1

「無」(nil)は当然ながら数値ではありません。そのためコードの13行目で、「for文の終端値は数字でないといけません」とエラーが出てしまったわけですね。

表示されるエラーメッセージはプログラムのミスを発見するのに役立ちます。特にエラーが発生した行番号の情報は重要です。その場所を中心に、なぜそのようなエラーが起きたのかミスを推測することができるからです。2

エラーが出ないように改造する

それではこのようなエラーがでないようにプログラムを改造しましょう。

改造のやり方はいろあるのですが、ここでは、「変数の初期値を決めておいて、引数が入力されたときだけその値に変更する」方向をオススメします。

つまり、次のようなイメージ。

  1. あらかじめ、変数hosuuの値を6に決めておく(数値は何でも好きにどうぞ)。
  2. もし引数に何か入力されたらそれを変数hosuuの値に代入する(つまり、何も入力されなかったら何もしない)。

という流れです。

if文の簡単な使い方

「もし◯◯◯ならば、△△△をする」

プログラムではこのような構文をよく使います。3 このような構文を表記するには、「条件分岐 if 文」を利用します。このif文自体は少々複雑なのですが、まずはシンプルなプログラムでif文の基本的な使い方を学びましょう。

以下のプログラムを「if0.lua」というプログラム名で保存して、様々な引数を入力して実行してみましょう。なお、--で始まる行はコメントですし、行の途中から--が入っているときはその--以降はコメントです。

以下、実行例。

> if0 10
10
> if0 20
20
> if0
6

このように「10」とか「20」とか引数を与えて実行すると、その引数を最終的に変数hosuuに代入してその値を表示します。また、引数を与えないと変数hosuuの初期値である6をそのまま表示するというプログラムです。

サンプルプログラムの詳細解説

まず3、4行目の変数定義部分は、ここまで記事を読み進めてきた人ならば何も問題なく理解できると思います。

(注意したいのは、3行目の表記によって「一番目の引数」が変数arg1に代入されることです。引数を複数入力しても、一番目のものだけ取り出します)

次にif文ですが、これは次のような構造をしています。

if 「条件式」 then
  「やって欲しいこと(複数も可)」
end

if、then、endの3つのキーワードが必須ですので位置も含めてしっかりと覚えましょう。

さて、この「やって欲しいこと」については、好きなこと書けばいいので問題ないとして、困ったのは「条件式」になります。これは何でしょうか?

真偽値

Lua言語における「条件式」は、結果として最終的に「真」または「偽」となる式を取り扱います。

・・・うん。難しいですね。つまりこの「条件式」の部分には真(true)または偽(false)のどちらかの値しか入らないのです。「真とは正しい」ということ、「偽とは間違っている」ということを意味します。

そしてこの真偽値によって、if文は挙動を変えるのですよ!

ちょっと例を示しましょう。

if true then
  print("shinndayo")
end

このプログラムでは、if文の「条件式」部分に「真(true)」がはめ込まれている。だからこのif文は続く「then 〜 end」の中を処理することになる。だから画面に"shinndayo"を表示する。

if false then
  print("shinndayo")
end

逆にこのプログラムでは、if文の「条件式」部分に「偽(false)」がはめ込まれている。だからこのif文は続く「then 〜 end」の中を読み飛ばして何もしない。画面表示もなし。

つまり、if 「条件式」 then 「やって欲しいこと」 endというif文は、「条件式」部分に「真」が入ると「やって欲しいこと」を実行し、「偽」が入ると読み飛ばしてしまうわけなのです。

さてここで、「真」「偽」というお話をしたわけですが、Lua言語ではもう少しこの真偽値を柔軟に取り扱っていて、true・false以外にも真偽の分類を広く認めています。それを次の表で説明しましょう。

偽 真
false, nil  ←この2つ以外全部

出ましたnil。これは「無いこと」を示す特殊な値でしたね。 Lua言語では、このnilとfalseは「偽」とします。 そしてそれ以外の全部の値を「真」とします。4

単純明快!!シンプル!!

さあこれで全体を説明するためのパーツの説明が揃いました。まとめましょう。

サンプルプログラムの解説

サンプルプログラムを再掲します。

まず、3行目で変数arg1の中に引数の一番目を代入しています。 もしプログラム実行時に引数を入力していればここには「何か(真)」が代入されていることになります。逆に引数が入力されていなければ、「nil(偽)」が代入されてます。

4行目は、変数hosuuの初期値として6を設定して定義していますね。

さあ、6行目のif文とその条件式です。今回条件式にはarg1をはめこんでいるわけでこれが真か偽かでif文は条件分岐するわけですね。

【引数が入力された「真」の世界】もし引数に何かを入力していれば、arg1は真なので、「then 〜 end」部分が実行されます。

つまり、hosuu = arg1ですね。arg1の値をhosuuに代入します5。 その結果、初期値が6だったhosuuは、引数の値によって上書きされました。

10行目。最終的に画面には、入力した引数がそのまま表示されます。

【引数が入力されなかった「偽」の世界】さて逆に、引数が入力されなかったらarg1はnilであり偽なので「then 〜 end」は読み飛ばされて下の行に進みます。

その結果、初期値6だったhosuuは手付かずそのままです。

10行目。最終的に画面には、初期値6がそのまま表示されます。

プログラムの最終形

これまでの説明を反映して改造した「yuka4」プログラムです。

便利に使い倒しましょう。そして、不便なところを見つけましょう。

次回はもっと便利に改造します。


  1. プログラム言語によっては、何も代入していない変数(初期化してない変数)の中に何が入っているのか不定な場合があります。実際に中を見るまで何かわからないとか怖っ! Lua言語では、何も代入していない変数の中身は「無」(nil)と決まっています。

  2. 実際にエラーが起きたのはたしかにこの行なのですが、そのエラーの根本的な原因はそれよりも前にあることが多い、ということは覚えておきましょう。今回の例で言うならば、「13行目のエラーの原因」は「6行目で引数を変数に代入しているけれどそもそも引数を入力してなかった」です。

  3. コンピュータの世界では、コード中に「もし◯◯◯ならば△△△をする」としか書かれていなかった場合、「◯◯◯ではないとき」には「何もしません」。つまりコンピュータは、命令されない限り何もしないというのが原則動作となります。

  4. nil,false以外の全部の値を「真」とするのはとてもシンプルですが、意外とくせものです。たとえば数値1ã‚„0、文字列"abc"は当然ながら真として、文字列"false"も真となります("“で囲んでいるのがポイント)。また文字列右""も真です(これは中身が空っぽの文字列で空文字と呼びます)。いじわる!

  5. この等号、数学の世界における「等しい」の意味じゃないですから気をつけて!プログラム言語の世界では、「arg1の値をhosuuに代入する」の意味で使っています。紛らわしいですが、現実世界ってそんなものです。割り切って覚えましょう。