latest log

酩酊状態で書いたエンジニアポエムです。酩酊状態で読んでください。

Ruby 風 mofmof.js

mofmof.js が String.prototype 等を拡張しているのは、Ruby などの OOP 言語の良さを取り込むためです。

mofmof.js に同梱されている es.jsruby.js を追加すると

  • Array#reject, select, flatten, map, each, or, and, fill, shuffle, assoc, index, uniq, collect, delete_at
  • String#insert, remove, to_f, to_i, to_s, sub, gsub, scan, strip, upcase, downcase, swapcase, ljust, rjust, center
  • Number#to_s, upto, downto, step

といった Ruby 由来のメソッドが利用可能になります。

mofmof.js では、PHPPython といった他の言語の基本的な API を追加で取り込もうとしており、API セットを切り替えるための実装も予定されています。

Ruby のコードを JavaScript に変換する Opal

MOONGIFT さんの Rubyで書いてJavaScriptに変換「Opal」を拝見し、
ちょっと気になったので比較してみました。

左が Ruby (Opal)、右が mofmof.js で書いた Ruby 風のコード

5..times do |i|
    puts "#{i+1} time#{"s" if i>0}."
end

[1, 2, 3, 4].each do |a|
    puts a
end

class Foo
    attr_accessor :name
end

adam = Foo.new
adam.name = 'Adam Beynon'
puts adam.name
5..times(function(i) {
    mm.say( "@@ time@@.".at(i + 1, i ? "s" : "") )
});

[1, 2, 3, 4].each(function(a) {
    mm.say(a);
});

adam = {
    set name(v) { this._n = v; },
    get name()  { return this._n; }
};

adam.name = "Adam Beynon";
mm.say( adam.name );

左が Ruby (Opal)、右が Opal で生成した JavaScript のコード

5..times do |i|
    puts "#{i+1} time#{"s" if i>0}."
end

[1, 2, 3, 4].each do |a|
    puts a
end

class Foo
    attr_accessor :name
end

adam = Foo.new
adam.name = 'Adam Beynon'
puts adam.name
(function() {
  var __opal = Opal, self = __opal.top, __scope = __opal, nil = __opal.nil, __breaker = __opal.breaker, __slice = __opal.slice, __range = __opal.range, __klass = __opal.klass;
  var adam = nil, __a, __b, __c;
  __range(5, (__b = self, __b.$times._p = (__a = function(i) {

    var __a, __b;
    if (i == null) i = nil;

    return this.$puts("" + ((__a = i, __b = 1, typeof(__a) === 'number' ? __a + __b : __a['$+'](__b))) + " time" + ((function() { if (i['$>'](0)) {
      return "s"
      } else {
      return nil
    }; return nil; }).call(this)) + ".")
  }, __a._s = self, __a), __b.$times()), false);
  (__c = [1, 2, 3, 4], __c.$each._p = (__a = function(a) {

    
    if (a == null) a = nil;

    return this.$puts(a)
  }, __a._s = self, __a), __c.$each());
  (function(__base, __super){
    function Foo() {};
    Foo = __klass(__base, __super, "Foo", Foo);

    var Foo_prototype = Foo.prototype, __scope = Foo._scope;
    Foo_prototype.name = nil;

    return Foo_prototype.$name = function() {
      
      return this.name
    }, 
    Foo_prototype['$name='] = function(val) {
      
      return this.name = val
    }, nil
  })(self, null);
  adam = __scope.Foo.$new();
  adam['$name=']("Adam Beynon");
  return self.$puts(adam.$name());
})();

mofmof.js も、現時点でかなり Ruby 風味なコードは書けるのですが、
まだまだ先は長そうですね。