読者です 読者をやめる 読者になる 読者になる

プログラマとプロマネのあいだ

プログラマもやるし、プロマネもやるし、たまに似非アーキとか営業っぽいこともやる

JScriptをRubyっぽくしてみる

前回
Windows Script Host Framework(wshf)見て、ラッパライブラリとはなんぞやと考えた。
の続きです。


JScriptJavaっぽくしてガンガン作りこんでいけば良いのでは?
という方向で考えていたのですが、下記ブログエントリを見て、
考え方を変えなければと思いました。

ちゃんとcloseを呼べばいいっちゃそうだが、ど忘れする時はあるからなあ。

その点、Pythonはwithを使えば確実にwithのスコープから抜けたときの処理を走らせることができる。

Javaっぽくしちゃうと、closeの呼び忘れ問題ってのが発生してしまうので、
やっぱりナシかなあと思った次第です。

サーバサイドJavaScriptを参考にしてみる?

で、既にサーバサイドJavaScriptとしての地位を確立している、
Rhinoやnode.jsを参考にすればいいんじゃないの?
と思って見てみたのだが、

ってことでRhinoは却下。
いや、もしかしたらRhinoを便利にするラッパライブラリとかあるのかも。


node.jsは、
hidekiy blog: [node.js] /dev/urandomを延々と出力するHTTPサーバー
を参考にしましたが、そこまで非同期にしなくても。。


ということで、Pythonあんまり知らないので、
僕にとって比較的親しみのあるRubyっぽくしてみたらどうよ?
ということで実装してみた。
お題は前回と同じ、ファイルのコピー。

ファイルをコピーするプログラムのソース

File.open("hoge.txt", "w", function(outfile) {
  File.open("file.js", "r", function(infile) {
    infile.each(function(line) {
      outfile.puts(line);
    });
  });
});

Rubyっぽくないですか?
ブロックじゃなくて、関数を渡すところは違いますけども。

ライブラリのソース

// Define Global Object wsh
var wsh = {};

// Create FileSystemObject
wsh.FSO = new ActiveXObject("Scripting.FileSystemObject");

// Constructor of File
var File = function(path, mode) {
  this.path = path;
  this.mode = mode;

  if(this.mode === 'w') {
    this.ts = wsh.FSO.CreateTextFile(this.path);
  } else {
    this.ts = wsh.FSO.OpenTextFile(this.path);
  }
};

// Static methods of File
File.open = function(path, mode, block) {
  var file = new File(path, mode);
  if(block) {
    try {
      block(file);
    } finally {
      file.close();
    }
  } else {
    return file;
  }
};

// Prototypes of File
File.prototype = {
  each: function(block) {
    while(!this.ts.AtEndOfStream) {
      block(this.ts.ReadLine());
    }
  },
  puts: function(line) {
    this.ts.WriteLine(line);
  },
  close: function() {
    this.ts.Close();
  }
};

というわけで

まあ、wshfを、よりrubyっぽくしただけと言えばそれまでなのですが、
一応できるっていうことは分かりました。
個人的には、Javaっぽいよりも、Rubyっぽい方が好きな気がします。
close忘れもないですしね。