組込み関連の仕事をしていることもあり、納品用に書いているコードはC言語かC++なのだが、納品物以外は別の言語で書くことが多い。テキスト処理にはsedやgawkを使うことが多いが、それ以外にもRubyやWSH + JScriptを使ったりする。
id:eel3:20080810 でも書いたが、小ツールを実装する時は標準入力とファイルのどちらからの入力にも対応できるようにしている。Rubyの場合、標準入力は組込み定数の STDINで、ファイルはFileクラスのオブジェクトだ。STDINはIOクラスに属していて、FileクラスはIOクラスを継承しているので、どちらも大体同じように扱うことができる。
if ARGV.size == 0 file = STDIN else begin file = open(ARGV[0], "r") rescue print "Cannot open file: ", ARGV[0], "\n" exit(2) end end begin file.each_line do |line| print line end rescue => e print "error raised: ", e, "\n" else # EMPTY ensure file.close end
WSH + JScriptの場合、標準入力はStdInオブジェクトで、ファイル(というかファイルへの入出力)はTextStreamオブジェクトだ。両者の関係は不明だが、まったく同名のプロパティとメソッドを持っているので、同じように扱うことができる。
// var stderr = WScript.StdErr; // var stdin = WScript.StdIn; // var stdout = WScript.StdOut; // var argv0 = WScript.ScriptName; // var args = WScript.Arguments; var file = null; if (args.length == 0) { file = stdin; } else { var filesystem = WScript.CreateObject("Scripting.FileSystemObject"); try { file = filesystem.OpenTextFile(args(0)); } catch (e) { stderr.WriteLine(argv0 + ": " + args(0) + ": open failed"); return 2; } } while (!file.AtEndOfStream) { stdout.WriteLine(file.ReadLine()); } file.Close();
動的型付け言語の場合、例え標準入力とファイル入力が継承関係のないオブジェクトで表現されていたとしても、両者が同名のプロパティやメソッドを持っているのなら、ソース上では同じように扱った実装をすることができる。こういうときDuck Typingって便利だよね、という話(蛇足ながら、C++のSTLとかも好き)。
ところで、面白いことに標準入出力とファイル入出力に関しては、静的型付け言語であるC言語でも両者を区別することなく扱うことができる。どちらもソース上ではFILE構造体へのポインタで、同じ関数を使えるからだ。Unix環境では更に標準入出力もファイル入出力もソケットもファイルディスクリプタで表現可能で、同じ関数で扱うことができる。
Tclの入出力まわりもUnixに近い。入出力はチャネル識別子という形で抽象化されていて、その中では標準入出力もファイルもパイプラインも同一に扱えるようになっている。
set input_from_stdin false if {$argc == 0} { set file stdin set input_from_stdin true } else { set argv1 [lindex $argv 0] if {[catch {set file [open $argv1 r]}]} { puts stderr "Cannot open file: $argv1" exit 2 } } while {![eof $file]} { gets $file line puts $line } if {!$input_from_stdin} { close $file }
これは私の妄想だが、少なくとも標準入出力とファイル入出力に関しては、Unix開発の比較的初期のどこかの段階で抽象化によって両者を区別せずに同じように扱えるようにするとメリットがあるという判断がなされたはずだ。Unixにパイプとリダイレクトが組み込まれて以降、その考え方はうまく機能していると思う。
もし標準入出力とファイル入出力が全く異なるものだったらと考えると、怖いものがある。C言語というかUnixの初期段階におけるデザイン選択のうまさを感じてしまうのだが、勘違いだろうか?