1.どの世代のプログラミング言語であるのか
2.どのような環境で動作するのか
3.変数の種類および取り扱い
4.演算子
5.[[制御構造]]
6.コメントの書式

先日の考察では、『3.変数の種類及び取り扱い』までをやってみたのである。

というわけで、『4.演算子』からということになろう。

4.演算子



ぶっちゃけたところ、プログラミング言語に演算子がないと、何もできないと断言してよい。別段、クラスがなくてもプログラムは作れるのだけれど。

なにせ太古の昔、コンピュータは『電子計算機』と呼ばれていたのだから。

無論今では死語だが。

計算機というぐらいだから、計算できなければならないのである。計算を行うためには、演算子がなければ話にならんというわけだ。プログラミング言語の話はちょっと横へおいておき、諸君、電子式卓上計算機、通称電卓を想起して欲しいのだ。

あれにあなた、+、-、×、÷、=のボタンが存在せぬとしてみよ。押した数字ボタンの数が順番に表示されるだけの機械に成り下がってしまうのだ。そのような数字表示機、価格が1円でも欲しくあるまい。逆に10円くれたっていらない。プログラミング言語においても、演算子が存在しないというのはそういうことになるわけだ。

さて、一口に演算子といっても、いくつかの種類があり、さらにそれぞれ細分化されるのである。

(1).算術演算子
算術演算子には、通常の計算用演算子と、プログラミング言語というか、コンピュータの世界ならではのビット演算子があるのだ。

さらに細分化すれば、計算用演算子には、単項演算子、二項演算子、そして三項演算子がある。ややこし過ぎるな。自分自身でもよくわからなくなってきた。

二項演算子というのはすぐに理解できるだろう。通常の四則演算は次のようなスタイルで行うのが一般的なのだから。

1+1
5ー3
8×8
10÷5

上記の+、ー、×、÷が二項演算子ということになるわけだ。二つの項から新たなひとつの数を導きだす演算子ということになるのである。コンピュータ上では、×とか、÷の1バイト文字がないので(なんでないのだろう?)、+、-、*、/ と表記するのだが。

ここでひとつ疑問が沸いてこないだろうか?例えば、

5-3+1

とか、

3*6-4/2

などの計算の場合、どう呼ぶのかということだ。それぞれ、三項演算子とか、四項演算子と呼ぶのであろうか?

いやさ。残念ながら、上記の式の中に登場する演算子は全て『二項演算子』なのである。

そもそも数値の計算というものは、数がたくさん登場してきたところで、一気にどばーっとやるわけではない。

例えば、 5-3+1の計算であれば、まず 5という項から 3という項を引いて 2という数、すなわち項を得て、それに 1という項を加算し、 3という結果、これまた項を導き出すのである。

要するに、いくら項がたくさんあったところで、単に、二項演算を繰り返し、繰り返しして結果を求めるに過ぎないのだ。

ではもうひとつの式、3*4-6/2はどうか?これはまず3と6の乗算を行い、18という項を得る。この項をちょっと横に置いて、4と2で除算を行い、2という項を得るのである。ここで先ほど横に置いていた18という項に登場してもらって、18から2を減算して、最終的に16という項を得るわけだ。

何故登場した順番に計算しないのか?それは『演算子には優先順位がある』からだ。*や/すなわち乗算や除算は、+や-すなわち加減算より優先順位が高いわけだ。これは、数学的にしっかりルールが定められていて、プログラミング言語仕様もそれに則って作られている。当たり前だ。演算子に独自の優先順位をつけようものなら、そんなややこしい言語は誰も使ってくれないのである。

この計算式で、まず最初に6-4を計算したい場合、一体どうすればよいのか。答えは簡単で、3*(6-4)/2 とすればよいのだ。()で式をくくると、まず()の中を先に計算しなさいというルールになる。

これはどういうことかというと、()は*/よりもさらに優先順位が高い『演算子』ということになるわけである。

四則演算の他に、Rubyでは次のような計算用演算子が用意されている。

5 % 3 剰算(整数除算の余りを求める)この例の場合、演算結果は2となる。

5 ** 3 べき乗(この例の場合、5の3乗で、結果は125だ)

二項演算子については理解いただけただろうか?

それでは、単項演算子とはなんであろうか?炭坑演算子ではないので注意が必要だ。

単項演算子には、次の二つが準備されている。

-a
+a

なんだこれはと思われた方もおられよう。ここでポイントとなるのは、これまでの演算子の例であれば1+1という風に、項が数字であったのだが、上記単項演算子の例では、aというアルファベットになっている。このaとはいったいなんぞやというと、16進数の Aすなわち10進数の10のことではなく、変数を現しているのである。単項演算子は、作用する項が変数でないと意味がないのだ。

なぜか?

それは、単項演算子を実際に使って動きを確認してみればよいのである。

諸君におかれては、お手持ちのパソコンにActiveScriptRubyをインストールされているだろうか?もしまだであれば、是非インストールしていただきたいのだが、絶対に嫌だとおっしゃる方には無理強いしない。お話だけ聞いていてもらいたい。

ActiveScriptRubyをインストーラー任せでお気楽極楽インストールすると、スタートメニューにRuby1.Xというグループが作成される。そこに『irb』というショートカットができていると思う。

irbとはなんぞや。『irb』とは、interactive rubyの略であって、対話方式でコマンドまたは式を実行でき、さらにその結果を表示してくれるツールだ。

せっかくこのような便利なツールがあるので、これを使って単項演算子を検証してみたいのである。

では、irbを起動してみよう。

先ほど申し上げたように、スタート→Ruby 1.X→ irbと選択してもよいし、スタート→Ruby1.X→Ruby Consoleと選択してDOSプロンプトを起動し、そこでおもむろにirbと入力してもよいし、もしRuby実行モジュールが格納されているフォルダにパスが通っているのなら、 DOSプロンプトで『irb.bat』(または、batを省略してirb)としてもよい。

なんなら、エクスプローラでRubyの実行モジュールが入っているフォルダ(例:c:\Program Files\ruby-1.8\bin)を開いて、irb.batをダブルクリックして起動してもよいのである。

irbを起動すると、次のような、極めてシンプルなコマンドプロンプト画面が開く。


それではまず変数を定義し、値を設定してみよう。

a=-3と入力し、エンターキーを押す。すると、次のように表示されると思う。


a=-3という式で、変数aにはもちろん-3という値が格納されたわけだが、この式自身の値も-3になったのだよということを現すのが、=>-3という行と考えていただければよい。

ではここでお待ちかね、単項演算子を使用してみよう。-aと入力してもらいたい。


いかがだろうか。ついに、驚くべき変化が現れたであろう。といってもそんなにたいしたことはないが。もともと-3という値を格納していた変数 aに、単項演算子 -(マイナス)を作用させると、符合が反転し、プラスになるのである。これは、算数の世界ではおなじみ、『マイナスにマイナスを掛けるとプラスになっちゃうよ』という法則をRubyが遵守しているに過ぎないのだ。

もし変数aが正の値を持っていた場合、単項演算子 -(マイナス)を作用させると、常識的にマイナスとなるわけだ。単項演算子には、 +(プラス)と -(マイナス)が存在するのだが、はっきりいってプラスの単項演算子はただの気休め、もともとの値が何も変わらないのだから、あまり意味がないのである。

さらに、これで単項演算子というものが、変数に作用してこそ意味があるというのもご理解いただけるのではないだろか。-3という式があったとして、これを記述した本人が『いいや。これは、3という数値オブジェクトに対し、マイナスの単項演算子を作用させたものなのだ。しかと相違ない』と、いくら主張したところで、世間一般には『ふーん。これは-3という定数なのだネ』と見做されてしまうからなのだ。

単項演算子の解説はこれにて終了し、次は三項演算子を解説したいわけだが、ちょっとその前に、単項演算子の動作確認に使用した対話型Ruby実行環境irbが非常に興味深いものなので、これについて触れておきたいと思うのだ。

irbの実行ファイル本体は、30行程度の短いバッチファイルである。では、そのバッチファイルの中身を見てみよう。

001 | @echo off
002 | @if not "%~d0" == "~d0" goto WinNT
003 | "C:\PROGRA~1\ruby-1.8\bin\ruby" -x 
      "C:/PROGRA~1/ruby-1.8/bin/irb.bat" 
      %1 %2 %3 %4 %5 %6 %7 %8 %9
004 | @goto endofruby
005 | :WinNT
006 | "%~dp0ruby" -x "%~f0" %*
007 | @goto endofruby
008 | #!C:/PROGRA~1/ruby-1.8/bin/ruby
009 | #
010 | #   irb.rb - intaractive ruby
011 | #   	$Release Version: 0.9.5 $
012 | #   	$Revision: 11708 $
013 | #   	$Date: 2007-02-13 08:01:19 +
         0900 (Tue, 13 Feb 2007) $
014 | #   	by Keiju ISHITSUKA(
              [email protected])
015 | #
016 | 
017 | require "irb"
018 | 
019 | if __FILE__ == $0
020 |   IRB.start(__FILE__)
021 | else
022 |   # check -e option
023 |   if /^-e$/ =~ $0
024 |     IRB.start(__FILE__)
025 |   else
026 |     IRB.setup(__FILE__)
027 |   end
028 | end
029 | __END__
030 | :endofruby

このバッチファイルのキモは、3行目の、

003 | "C:\PROGRA~1\ruby-1.8\bin\ruby" -x 
      "C:/PROGRA~1/ruby-1.8/bin/irb.bat" 
      %1 %2 %3 %4 %5 %6 %7 %8 %9

の部分である。ここで一体なにをやっているのかというと、自分自身を、C:\PROGRA~1\ruby-1.8\bin\ruby すなわち、Ruby本体(Rubyのスクリプトを解析し、実行するインタプリタプログラム)に引き渡しているのである。

その後、4行目の、

007 | @goto endofruby

で、ファイルの最終行までぶ飛んでいる。すなわち処理を終了しているのである。

Ruby本体にどのような内容が引き渡されるのかというと、17行目から29行目が引き渡され、実行されるわけだ。ここがプログラムの中身になる。

で、どんな処理をしているのかというと、if文でいろいろと判定して、ごそごそとやっているけれども、大事なのはこれ、

IRB.start(__FILE__)

の部分に他ならない。

17行目のrequire "irb"で、外部定義クラスIRBをインポートして(使用可能にして)、そのIRBクラスが持つ静的メソッド、startを呼び出しているのだ。

コマンドプロンプトからユーザの入力を受け付け、解析実行する機能が全をこのIRBクラスが持っており、startメソッドを呼び出すことにより、それが実行されるということになるわけである。

当然このIRBクラスの定義は、Rubyで記述されているのである。さすがはオブジェクト指向であると、そのパワーをまざまざと思い知らされたことと思うし、また、これまでVisualStudioなどを使い、Windows専門のアプリケーションばかりを作成してこられた方には、このバッチファイルの中にスクリプトを埋め込み、インタプリタを起動して云々という記述が、異質であるが面白いものに感じられると思ったので、時間を割いてご紹介してみたというわけである。

さて、計算用演算子の最後は、三項演算子である。

三項演算子とはなにかというと、読んで字のごとく、演算が作用する項が三個存在する演算子のことである。

こんな感じだ。

3 + ( a<4 ? 1 : b )

なにやら数字や変数が三個以上出てきてややこしいけれども、項に当たるものはどれどれかというと、

3、1、b

の三つだ。では a<4 というのは何かというと、条件判定式なのである。

三項演算子の一般的な形式は次のようになる。

<式> ? <真の場合の式> : <偽の場合の式>

従って、?と:ペアで、三項演算子と呼ぶのである。

サンプルの式では、最終的に、 3に、なにかしら値を加算したいのであるが、変数 aの値が4未満であれば1を、4以上であれば変数bに格納されている値とするわけだ。

これもできれば、めいめいirbで動作を確認しておいていただきたい。

変数a、bにそれぞれ任意の値を格納して、式を実行するのである。


おっと。これは余談であるが、Rubyには残念ながら、というか幸運にもと言うべきなのか、C言語ファミリー(Javaも含めて)にある、インクリメント演算子、デクリメント演算子はない。

a++や、--aというやつだ。

これは非常に便利なのだが、使い方を誤ると思わぬ誤動作を引き起こす可能性がある(言語側からすると予定の動作なのだが、人間様の思惑から外れるということ)。という理由からかどうかは不明だが、とにかくRubyには準備されていない。

よろしいかな。では『ビット演算子』に話を移そう。

(ii).ビット演算子
最近の若き、未来あるプログラマの方は、もしやビット演算などご存じないかもしれない。なぜかというと、教育担当者や先輩が教えないことが多いからだ。

なぜ教えないのかというと、知っていても、使用する局面に遭遇しないからだ。このオブジェクト指向プログラミング全盛の時代では。ちまちまとビットを操作している暇があれば、フレームワークの使い方でも勉強せよというわけなのである。

しかし、全く使わないかというとそうでもなく、時折ビット演算処理が見え隠れする場合もあるので、知識として知っておいたほうがよいだろう。

Rubyのビット演算子には、以下のものが準備されている。


~a     ビット否定(not) 
a & b  ビット積(and) 
a | b  ビット和(or) 
a ^ b  ビット排他的和(xor) 
a << b 左シフト(a を b 回左シフト) 
a >> b 右シフト(a を b 回右シフト) 

各演算子の働きについては、皆さんirbで試してみて欲しい。

例えば、|(ビット和or)ならば、


などという風に。

さて、これで算術演算子の解説は終わりだ。

では次に『代入演算子』の説明をしよう。

(2).代入演算子
代入演算子とは、ある変数に値を代入するときに使用する演算子である。算術演算子を解説するときに、既に何度も登場しているから、既にみなさんも見当がついていると思う。

a=1

と、この = が、代入演算子である。上記の式では、変数aに1という値が代入される。というのは、Ruby的に正しくなく、『数値の1というオブジェクト』の参照を変数aが持つのである。

日本語的に表現すると、この式は『aの値は(=)1なんですよ』と言っているわけであって、非常に明瞭なものなのだが、この代入演算子 (=)を『aと1とは等しいですよ』という比較にも使用している、若干困り者の言語があるのをご存知の方もおられるだろう。

VisualBasic言語がそうである。

かの言語の場合、文脈でどちらかを判断するようで、まあよく考えてあるとも言えるが、なんとなく寝覚めの悪さを感じる方もおられよう。

では、Rubyはどうか?ご安心いただきたい。この後で解説するが、比較演算子の等値は、C言語ファミリーと同様に == と記すようになっている。

代入演算子の右辺には、二項演算子を記述することもできる。

a=3+4

上記の式では、当然のことながら変数aには7が代入されるのだ。だが、当然と言い切るにはやはりあるルール付けが必要になってくることは言うまでもない。

なぜならば、上記の式は、『まず変数aに3を代入して、その後 4を加算する。すなわち、変数aの値は3となり、式全体が持つ値が7となるのだ』という解釈も成り立つはずだ。結果は同じだけれど、計算の順番が違ってくることに注目していただきたいのだ。

しかし残念ながらというか、幸いなことにそうはならない。

なぜならば、算術演算子 + は、代入演算子 = より優先度が高いから、まず3+4という式が評価されて、その値がaに代入されるということになる。

無理やり先ほどの解釈の通りにしたければ、

a=(a=3)+4

と、aに対する3の代入を()でくくって、演算結果を改めてaに代入すればよいというわけだ。非常に回りくどいけれども。

代入演算子とは基本的に = のみと考えてよいわけだが、『自己代入』という便利な記述方式がある。ある値を保持している変数があるとして、その値に別の値を加減乗除もしくはビット演算した結果を持たせたいとすると、どのように記述するだろうか。言葉で表現すると非常に回りくどいが、式にしてしまうと簡単だ。

a=10
a=a/2

これは、10という値を持っているaという変数があって、その値を2で除算した結果をまた変数aに代入するのである。変数aの値は5となるわけだ。別にこれはこれで何の問題もない。

だが、いるのである。やはり『a=a+1 なんて書くのは面倒ダナ』というズボラな連中である。

というか、こういったズボラな連中が、もっと簡単に素早くできる方法はないものかと模索してきた結果、プログラミング言語が今日このように発展してきたともいえる。勿論、ズボラといってもそんじょそこらのズボラではなく、天才的なズボラでなくてはならないのだけれど。

とまあ、そこで登場したのが、『自己代入』の記述方式なのである。自己代入の書式では前出のa=a/2の式は、次のようになる。

a/=2

Rubyにおける自己代入の書式をリファレンスマニュアルに求めてみると、次のようになっている。


文法:

式1 op= 式2     # 式1は通常の代入の左辺のいずれか
op は以下のいずれかです。演算子と=の間にスペースを空けてはいけません。

+, -, *, /, %, **, &, |, ^, <<, >>, &&, ||

さらに、Rubyには、『多重代入』という機能が提供されていて、次のような記述が可能だ。

a, b, c = 1, 2, 3

見た目の通り、変数aには1、bには2、cには3が代入されるのだ。実に当たり前なのであるが、ほとんどのプログラミング言語で、この当たり前の記述を行うことができないのである。

多重代入機能は、Perlを流れをくむ、スクリプト系言語の専売特許といっても過言ではないだろう。

代入演算子についてご理解いただけたところで、次に『関係演算子』の説明に移ろう。

(3).関係演算子
関係演算子とは、値の大小を比較する条件式で使用する演算子のことである。比較演算子と表現する場合もある。

Rubyには、次のような比較演算子が準備されている。

a < b       a は b より小さい(b未満) 
a <= b      a は b より小さいか等しい(b以下)
a > b       a は b より大きい(b超過)
a >= b      a は b より大きいか等しい(b以上)
a == b      a は b と等しい
a != b      a は b と等しくない
a <=> b     a と b との大小を返す。
             (a < b なら負、a == b なら0、a > b なら正)

関係演算子の式は、条件を満たせばその値が真(TRUE)となる。この関係演算子が活躍する局面は、やはりifによる条件分岐となるわけだ。

if a < b then
   # 真(TRUE)の時の処理
else
   # 偽(FALSE)の時の処理
end

関係演算子自体には、これ以上特筆すべきことはない。

ただし、最後の a<=> b という書式は、他のプログラミング言語ではあまり見かけないので、驚かれた方もおられるだろう。

説明をよく読んでみると、変数aと変数bに、整数であれ実数であれ、数値が入っていた場合、a - b という算術演算をしたのと同じなのである。ただし、この演算子は、算術演算子をオーバーライドしていないけれども、なんらかの大小関係があるクラスのインスタンス間では有効だ。

さて、残念ながら、単純に二項だけを比較するのみでは、とてもではないがまともに動くプログラムは作れない。何が言いたいのかというと、実際にプログラムを作成するにあたっては、条件判断というものは、もっともっと複雑になりがちであるということだ。

例えば、『ある変数の値が、2以上でかつ、5以下の場合』とか、『変数aの値が3で、かつ変数bの値が8の場合』とか、『変数aの値が4か、変数bの値が7か、どちらかの場合』と、いくつかの条件組み合わせて判定しなければならない局面が往々にしてあるのだ。

そこで登場するのが、『論理演算子』なのである。

(4).論理演算子
論理演算子は、前項の関係演算子の解説で出てきた、『かつ』とか『または』を式として表現するものなのである。

!a          論理否定
not a       論理否定(!aと同様の意味)
a && b      論理積(かつ)|
a and b     論理積(&&と同様の意味)
a || b      論理和(または)
a or b      論理和(||と同様の意味)

前出の『ある変数の値が、2以上でかつ、5以下の場合』を論理演算子を使って表現してみると、次のようになる。

a>=2 && a<=5

または、

a>=2 and b<=5

上記二つの式は、日本語の文章をそのままプログラムの式に移し変えたものだが、論理的には次のように書いても有効だ。

a>1 && a<6

または、

a>1 and a<6

2以上ということは、1より大きいということだし、5以下ということは6未満なのだから、これらの式は論理的に正しいということになる。

さて、ここで疑問に思っていただきたいことがあるのだが、!とnot、&&とand、||とorは、同じ意味なのだ。それぞれ、論理否定、論理積、論理和である。
ではなぜ、それぞれ二種類存在するのであろうか。これもまたRubyの特色で、他のプログラミング言語で、このように論理演算子を二種類用意してあるものは少ない。なぜならちょっと混乱するからだ。

実は、Rubyにおいては、これら対応する二種類の論理演算子に、評価される優先順位を設定している。

!、&&、||は、それぞれnot、and、orより優先順位が高い。

a==1 && b==2 || c==3

上記の式を書いた実装者の思惑としては、bが2かまたはCが3で、かつaが1のときのみ真となって欲しいのだが、残念ながらそのような結果にはならない。

Cが3でありさえすれば、a、bの値はなんの意味もなく、この式は真となってしまうのである。

実装者君の思惑通りの結果を得るためには、

a==1 && (b==2 || c==3)

とすればよいのだが、Rubyでは、次のように記述できるということである。

a==1 and b==2 || c==3

このように、論理演算子の表記方法が二種類存在し、それぞれに優先順位がつけられていると、非常に便利なように見える(実際に便利なのであるが)。

だが、あまり多用されないほうが賢明ではないかと私などは思うのである。なぜなら、先ほども述べたように、論理演算子を二種類用意しているプログラミング言語は少ないから、他のプログラミング言語で開発せざるを得なくなったときのために、同一優先順位の演算子を使い、()で順番を明確にするという書き方を平素から勤めておくべきだと、老婆心ながら思う次第だ。

以上で、『算術演算子』、『代入演算子』、『関係演算子』、『論理演算子』と見てきたわけだが、一応これで、普遍的な演算子を解説し終えたことになる。

しかし、演算子の種類はこれだけではなく、プログラミング言語には、おのおの趣向を凝らした特殊なものが他にも用意されている。Rubyにも当然あるのだ。

(5).範囲演算子
a..b        a 以上 b 以下の値の範囲
a...b       a 以上 b 未満の値の範囲

と、演算子の書式説明をしただけでは、一体どのように使用するかよくわからないかもしれない。

範囲演算子は、例えば次のように使用する。

(1..10).each { |i|
    puts i.to_s
}

コードを眺めているだけで、このコードが何をやっているのかはぼんやりとお分かりになるのではと思う。そう、 1から10までの数字を順番に画面表示しているのだ。ではこのコードをirbで確認してみよう。


irbは、そのまま使用すればワンライナー(1行プログラム)のみ受け付けるのだが、上記のように、最初の行で何も入力せず、リターンキーだけを押すと、複数行モードになる。

複数行モードとなったサインは、>が、*に変わることだ。そのままどんどん入力していって、とりあえずコマンドが完結したとirbが判断すれば、勝手に実行してくれるのだ。

上記の例では、4行目の}を入力した時点で、コマンドが完結したと判断され、実行されるのである。

1から10まで順番に画面表示されているのがわかるだろう。

このコードのキモは、どう見ても範囲演算子で構築された、(1..10) というモノだ。ではこれは一体何物なのかというと、これもまた『オブジェクト』であり、『Rangeクラス』のインスタンスなのである。

この Rangeクラスが、内部要素を順に繰り返し処理する、eachメソッドを持っているということになるわけだ。

であるから、明示的に次のようにして生成することも可能である。

robj = Range.new(1,10)
robj.each { |i|
    puts i.to_s
}

ではこれも、irbで確認してみよう。


irbの実行結果を見てみると、Rangeクラスのインスタンスの生成で、1..10のRangeオブジェクトが生成されているのがよくわかると思う。

次の二行だ。

irb(main):002:0* robj = Range.new(1,10)
=> 1..10

(6).マッチング演算子
『正規表現(regular expression)』という言葉を聞かれたことがあると思う。『正規表現』とは、単独または連続した文字列が、ある特定のパターンに適合するかどうかを検査するための書式のことだ。

『正規表現』を真剣に解説しだすと、平気で本一冊終わってしまうので、世に正規表現の解説書は多く出版されているし、インターネットでも多くの有識者が解説しているので、そちらを参考にしていただきたい。

マッチング演算子には次のものがある。

/r/ =~ a    aが正規表現rにマッチするなら
a =~ /r/    aが正規表現rにマッチするなら
/r/ === a   aが正規表現rにマッチするなら
a === /r/   aが正規表現rにマッチするなら
/r/ !~ a    aが正規表現rにマッチしないなら
a !~ /r/    aが正規表現rにマッチしないなら

以上で演算子の解説は終了である。
最終更新:2008年12月27日 19:37