プログラミングの技紹介(or演算子をif文の代用にする)

今日、東京の千代田区(市ヶ谷)に一日中いた。その時に、ノートPCを持っていたのでPerlTCP/IPの通信プログラムを実装していた。ローマ法王庁大使館付近でWiMAXが15Mbpsだして少し感動した。1.9Mbyte/sで通信できるなんてもうウヒヒだよね。それはいいとして、Perlのソケットプログラミングについていろいろと調べていると以下のようなプログラムの書き方をしたものがありました。一部抜粋。

my $sock;
socket( $sock, PF_INET, SOCK_STREAM, getprotobyname('tcp' ) )
    or die "Cannot create socket: $!";

これはperlにおいてソケット作成する部分のプログラムです。ちなみに、$sockはハンドラで、PF_INETは通信対象ドメインを指定し、SOCK_STREAMはTCPを使用することを表していて、getprotobyname('tcp' )は、トランスポート層プロトコルを指定しているものです。さて、この or dieとはどういう意味なんだろうか。dieは、perlで例外を吐くときにつかうあのdie。

論理和(OR)は2つのオペランドの値のどちらか、または両方とも true のときに true、それ以外のときには false を返す論理演算です。

perlのorはC言語でいうと、ll(論理演算子論理和)に当たる物。おそらく、このプログラムはソケット作成関数が偽(FALSE)を介したとき、Cannot creat socketの例外を出すという思惑があるのだろう。普通はif文を使うのがナチュラルであり、対象関係のこの両者をor演算するとかマジイミフ。ただ、他のサイトでもこういう記述をよく見るのでミスではないだろう。まぁソケットプログラミングに限ったことではなく、or dieはperlプログラマーにとってはプログラミングのテクニックのひとつなんだろうなーと思い調べた。

実は、or演算は、左辺から式が評価される。左辺に関数を書いておけば、評価されるため、関数は実行され返り値を戻してくる。で、or演算子ではもし、左辺が真(TRUE)の場合は、or演算自体のTRUEが速攻決定されるので、右辺値の値を評価する必要性がなくなる。と、いうことは、左辺値がTRUEならOR演算の結果は右辺値に依存せず、TRUEとなる。よって右辺は評価されない。=実行されない。
上記の例の場合、ソケット作成関数が成功(TRUE)になったら、右辺で定義されている例外処理(エラー処理)は実行されずに済む。
逆に、左辺値が偽(FALSE)の場合はどうなるだろうか。左辺がFALSEだったら、次に右辺値が評価される。=右辺の関数が評価(実行)される。

ここまで言えばもうお分かりかもしれない。最後のまとめはいろう。

関数1(例外チェックする関数とか) or 関数2(エラー処理(例外処理))

という行があったとする。まず左辺を評価する(関数1が実行される)。左辺(関数1)がFALSEの場合→右辺値は評価される。(実行される)。左辺(関数1)がTRUEの場合→右辺値は評価されない。(実行されない)
つまり、if文と同じ事を関係演算子のorで実装できている。

まさにプログラマーとして覚えておくべきのテクニックだと思った。もしかしたらプログラミングの世界では常識だったりするのかもしれないが、恥ずかしながら今日知った。
以上のことをC言語でも実装できるかテストしてみた。

#include<stdio.h>
int func(){
	return 1;
}
int main(){
	func() || printf("Func.");
	if (!func()) {
		printf("Func.");
	}
	return 0;
}

MacOS+gcc環境で、perlと同じことを出来ることを確認した。perlの場合はorが||はほぼ同等だけど、C言語だと 論理演算子でorなんてないからね・・・。この技は多分たいていのコンパイラーで使えると思う。ただ、コンパイル時にor演算で両方の入力を評価するコンパイラーは使えないかな。それからperlにおいてorと||は評価の優先順序があるみたいです・・・。同じものだと思っていましたけど、厳密には違うようです。ということで、今日はひとつ技を紹介しました。

追伸:この事をtwitterにて投稿したところ、やはり入門書にも書いてある常識である事を教えていただきました。
もしかしたら知らない人用にこの記事は残しておきます。