プログラミングの世界では式の評価という言い回しが登場する。
VBAの書籍では見かけない言い回しであるが、関数やオブジェクトの動作について説明・理解するのに便利な概念なので覚えておくと良い。
式といえばまず数式をイメージする方が多いだろう。あの忌まわしい数字と記号の羅列である。(数学好きな人、ごめんなさい。)
また、評価という言葉は、「高評価・低評価」など、一般的には物の良し悪しに言及する際に用いられるが、プログラミングにおいては値を確定するという意味で用いられる。
ふつう、数式に対して答えを導く操作は「計算」という。
なぜプログラミングでは式に対し「計算」という語の代わりに「評価」という語を用いるのだろうか。
その理由は、実はプログラミングにおける式は数式だけではないからだ。たとえばオブジェクト式・比較式・論理式・関数・変数・定数・リテラル・文字列の結合などもすべて式である。
式=数式のイメージが離れない方は、式という言葉の定義に立ち戻って考えてみよう。式とは、記号・数字などを用いて物事の関係・構造などを表したものをいう。プログラミング以外でも、たとえば分子構造を表す化学式は、計算しない式の代表選手である。
プログラミングにおいても数式に対してはより直観的な「計算」という語を用いる場合が多いが、「計算」という語は加減乗除のイメージが強く、文字列の結合やオブジェクト式などに用いるには違和感がある。そこで、数式以外でもより汎用的に使える「評価」という言い回しが用いられる。
式が評価されるプロセス
さて、実際に簡単なプログラムコードを使って評価のプロセスを見ていく。
繰り返しになるが、ここでいう評価とは何らかの操作を行って式の値を確定することである。何らかの操作とは、計算かもしれないし、結合かもしれないし、参照かもしれない。それらをひっくるめて言い表せる便利な言葉なのだ。
数式の評価
まずは以下の代入文を例に説明する。
x = (1 + 1) * 2
xに4が代入されるという一目瞭然なことを、あえて細かくプロセスを追っていくが、難しいことではないので字面通りに注意深く読んでほしい。
代入文の形式は「変数(またはプロパティ) = 値」であるが、上記コードの場合、右辺にあるのは式である。式は評価されて値になるので「変数 = 式」という書き方も結局は「変数 = 値」と同等であると言える。
上記のコードではまず(1 + 1)が評価され2になる。次に2 * 2が評価され4になる。これでx = 4という「変数 = 値」形式のシンプルな代入文が完成した。このように、式はプログラムの内部で最初に評価され、値になった後に文法のパターンに当てはめて処理される。
関数の評価
先に述べたように、関数も式の一種である。以下の代入文を例に、関数の評価プロセスを追っていく。
m = Left("Hello, World!", 7) & StrConv("vba", vbUpperCase)
Leftは文字列を左から切り取る関数、StrConvは文字列の形式を変更する関数である。
このコードではまずLeft関数が評価され、
m = "Hello, " & StrConv("vba", vbUpperCase) となる。
次にVBAの組み込み定数であるvbUpperCaseが評価され、
m = "Hello, " & StrConv("vba", 1)となる。
次にStrConv関数が評価され、
m = "Hello, " & "VBA"となる。
次に文字列の結合が評価され、
m = "Hello, VBA"となる。
これで代入文の形式「変数 = 値」ができた。
オブジェクト式の評価
最後にオブジェクト式が評価されるプロセスを見ていく。オブジェクト式の形式は、「オブジェクト.プロパティ」または「オブジェクト.メソッド」である。たとえば以下の式の左辺は一見、「オブジェクト.オブジェクト.オブジェクト.プロパティ」のように見える。そのように理解しても当面は問題ないが、変則的なコードに出くわすと応用が利かないので、ここで詳しく説明しておく。
ThisWorkbook.Sheets(1).Range("A1").Value = 1
実際にはまず、ThisWorkbook.Sheets(1)が「Workbookオブジェクト.Sheetsプロパティ」として評価され、Worksheetオブジェクトになる。
次に「Worksheetオブジェクト.Rangeプロパティ」が評価され、Rangeオブジェクトになる。
最後に「Rangeオブジェクト.Valueプロパティ」に1が代入されるというプロセスである。
このように評価プロセスに注目すれば、最後まで一貫して「オブジェクト.プロパティ」のシンプルな形式を保っていることが分かる。
さて、もう少し実践的なコードでオブジェクト式の評価を追ってみよう。
Sub test() Dim WB As Workbook Set WB = Workbooks.Open("C:\Work\test.xlsx") WB.Sheets(1).Range("A1").Value = 1 WB.Save WB.Close End Sub
上記のコードを1行ずつ解説していく。
Dim WB As Workbook
Workbook型の変数WBが作成される。
Set WB = Workbooks.Open("C:\Work\test.xlsx")
WorkbooksオブジェクトのOpenメソッドが評価され、Workbookオブジェクトになる。そしてWBにWorkbookオブジェクトが代入される。
ここで、「おや?」と思われた方もいるだろう。プロパティが評価されるのは分かるが、メソッドが評価されるというのはどうも不可解に思われるかもしれない。実はメソッドには値を返すものと返さないものがある。再度繰り返すが、評価とは値を確定することである。つまり値を返すということは、そのメソッドは式として評価できるということである。
WB.Sheets(1).Range("A1").Value = 1
変数WBが評価され、Workbookオブジェクトになる。Workbookオブジェクト.Sheetsプロパティが評価されてSheetオブジェクトになり、Sheetオブジェクト.Rangeプロパティが評価され、Rangeオブジェクトになる。そしてRangeオブジェクト.Valueプロパティに1が代入される。
WB.Save
変数WBが評価され、Workbookオブジェクトになる。Workbookオブジェクト.Saveメソッドが実行され、ブックが保存される。
WB.Close
変数WBが評価され、Workbookオブジェクトになる。Workbookオブジェクト.Closeメソッドが実行され、ブックが閉じられる。
サンプルコードの流れは以上である。非常に面倒くさい書き方をしてきたが、ここで注目したいことが2点ある。
まず1点目は、オブジェクト変数はあくまで入れ物であり、中身を評価されて初めてオブジェクトとして扱えるということ。2点目は、やはり一貫して「オブジェクト.プロパティ」、「オブジェクト.メソッド」という基本の形式が守られているということだ。
次に、先ほどと同じ動作をするコードを少し変わった形に書き直してみた。
Sub test2() Dim R As Range Set R = Workbooks.Open("C:\Work\test.xlsx").Sheets(1).Range("A1") R.Value = 1 R.Parent.Parent.Save R.Parent.Parent.Close End Sub
オブジェクトを単に入れ子構造として理解していると、上記のコードは「Workbookオブジェクト.Openメソッド.Sheetオブジェクト.Rangeオブジェクト」のように見える。
「ちょっと待てよ、なんでメソッドの後にドットを続けてオブジェクトを書けるんだ」と思われるかもしれない。しかし先ほどのオブジェクト式の評価のプロセスを思い出せばコードの意味は簡単に理解することができる。
さて、詳細の説明は省略するが、最後のParentはあまり見かけないと思うので、ここで解説しておく。
Parentは、親要素を指定するプロパティである。Rが評価されるとRangeオブジェクトになり、Rangeオブジェクト.Parentプロパティが評価されるとRangeの親要素であるWorksheetオブジェクトになる。Worksheetオブジェクト.Parentプロパティが評価されるとWorksheetの親要素である。Workbookオブジェクトになる。最後にそれぞれWorkbookオブジェクトのSaveメソッド、Closeメソッドが実行されている。
おわりに
さて、今回は「式の評価」という言い回し・概念について詳しく解説した。これはつまり、コードがやっていることを的確に表現する言葉を手に入れたということである。
新しい概念を獲得し、言葉によってそれを脳内辞書にマッピングしておく。回りくどいようだが、私はそれが物事の理解への早道になると信じている。今回の記事が読者のプログラミング上達の一助になれば幸いである。
なお、今回最後に紹介したコードはあくまでオブジェクト式の評価のプロセスを説明するためのサンプルなので、実務で参考にすべきコードではないということを改めて断っておく。何事もシンプルが一番である。
以上