クリスマスRubyをつくろう!

12月になりました。最後のRubyKaigiで私は「クリスマスは自分なりのRubyをmatz&コミッターの人たちに贈ろう」と提案したわけですが、みなさん準備の方はいかがでしょうか。

[18S01] Parse.y Famtour (ja) from ogi on Vimeo.

え、全然進んでないどころか、そんなんやる気ない?それはいかんですね。

RubyKaigi亡き今、感謝の気持ちはコードで表すしかありません。そんなこともできないようではRubyのエラい人たちにRubyユーザーはバカとか思われてしまいます。ここは一つ彼らの発想の斜め上を行く機能をRubyに追加して、「俺たちはバカじゃない!大バカなんだ!!」ということを思い知らせてやるべきでしょう。

そこまで言うなら一つやってみるかと思いましたか?思いましたよね。そこで問題になるのが、どういう機能を追加するかです(実際にどう作るかは上の動画を参考にしてください)。

追加したい機能もないのに、とにかく機能を追加しようするなんてバカだと思う人もいるかも知れませんが、俺たちはバカじゃない!大バカなんだ!!

ということで、今日はクリスマスRubyの機能を考えるヒントについて書いてみたいと思います。

Boys, don't be ambitious.

まず大事なことは、あまり大げさな機能を追加しようとしないことです。多大な時間を浪費した上で失敗します。そもそもそれが実現できる人はオレオレRubyなんてやってる場合じゃありません。溜まってるIssueを解決してクリスマスプレゼントにはpatchを送ってあげましょう。

既存キーワードの置換 or 別名

一番簡単な機能追加は、機能を追加しないことです。C言語知らないし、Rubyソースコードなんて見たことないという人はこの辺から試してみましょう。それだけでも動けば意外と感動しますよ。

例えば、Ruby の各種予約語が定義されている defs/keywords を開き、"def" の定義をコピーして次のように変更し、make してみます。

function, {keyword_def, keyword_def}, EXPR_FNAME

これだけでなんとなく JavaScript っぽく関数定義できるようになります。

function greeting(name)
  "Hello, #{name}"
end
puts greeting('function')


ただ、ここで一つ注意点があります。当たり前の話ですが、新しい予約語Rubyコード内で頻出する単語にすると miniruby 以降でいろいろとエラーが出て make に失敗します。今回も def を sub に、class を package にして「Perlっぽくなった」って言い張ろうと思ったんですが、sub でエラーが出まくるのでやめました。そりゃそうだ。

無視される要素の追加

さらに一歩進んで、文法要素を追加するけど、機能は追加しないという手もあります。

def fully_typed_method(arg : String) : String
  arg
end
var : String = fully_typed_method('var')
puts var

例えば先日公開した Optionally Typed Ruby の型宣言っぽい部分は実際にはただのコメントで何もしません。こちらは元の構文をコピペして、無駄なトークンをはさみ、そのトークンの値を無視することで実現しています。これはひどい

さらに簡単な方法としては parser_yylex 関数内で特定の文字の並びをスキップするという手もあるでしょう。例としては、少し違いますが、予約語内の連続する文字を無視する Rruuubbyyyy があります。

moooodddulee Foo
  cclllasss Bar
    dddeeefff xyzzy
      iiffff tttrrueee ttheeen
        p :hheeellooo
      endd
    eeend
  ennndd
eeendd
Foo::Bar.new.xyzzy


もちろん一部の無視キーワードを追加するだけでオレオレRubyと言い張るのは寂しい物がありますが、先ほどの既存の予約語の別名と組み合わせることで、労せずしてなにか面白いことができるかも知れません。

%記法の追加

機能を追加するのであれば、比較的簡単なわりにいろいろと大それたことができておすすめなのが%記法の追加です。%記法を知らない方はいないと思いますが、一応書いておくと、こういう記法のことです。

%q(Hello, world!)
%r|https?://(\w+\.)+\.\w{2,3}/|
%w{one two three}

%記法は、parse.y の parser_yylex 関数内に、'%'のあとに'w'が来たらとか、'q'が来たらとか書いてある部分があるので、その辺り適当にコピペして新しいトークンを返し、中の文字列を prelude.rb で定義したメソッドでゴニョゴニョすれば割となんでもできます。'%'の後に使える文字もまだまだたくさん空いていて選び放題です。利用例としては Objective-Ruby があります。

require 'date'
birthday = %o{ Date new:1993 month:2 day:24 }
if birthday == %o{ Date today }
    puts "Happy birthday, Ruby!"
end

%o記法内ではメソッド呼び出しの表記が Smalltalk 風に代わってます。Objective-Rubyについては RubySmalltalk 文法っぽいものを解釈しているので意外と面倒くさいことになっていますが、そこまでやらなくてもアイデア次第でいろいろできるでしょう。

ヒアなんとかの追加

%記法と同様にヒアドキュメントも、周辺のコードをコピペしていろいろできます。ヒアなんとかを作るとソースコードの見た目を一気に変えることができるので、見た目のインパクトを重視したい方にはおすすめです。ただし、%記法より少し実装が面倒で制約も大きいので使いどころが少し難しいかも知れません。利用例としてはヒアXMLを実装した XML Ruby とヒアYAMLを実装した YAML Ruby があります。

http://d.hatena.ne.jp/technohippy/20091225

phone_book = <?xml>
  <phonebook>
    <descr>
      This is the <b>phonebook</b> of the
      <a href="http://acme.org">ACME</a> corporation.
    </descr>
    <entry>
      <name>Burak</name>
      <phone where="work">  +41 21 693 68 67</phone>
      <phone where="mobile">+41 79 602 23 23</phone>
    </entry>
  </phonebook>
</xml>

http://d.hatena.ne.jp/technohippy/20111112#1321081902

data = ---
  a: 1
  b: 2
  c: 3
...

さいごに

たった4つだけですが、オレオレRubyのネタを考えるヒントを紹介しました。これらを参考に(してもしなくても構いませんが)、少しでも Ruby の改造に興味を持ち、作った変 Ruby を公開する人が増えると嬉しく思います。

作ったはいいものの公開をためらう人もいるかもしれません。しかし、そもそもオレオレRubyはオレオレなので完璧である必要はありません。文法に多少の矛盾があっても、特定のサンプルコードがなんとなく動作すれば文句をいう人はどこにもいません。文句どころか実際に試してくれる人もほとんどいないでしょう(´・ω・`)ショボーン…

また、途中で諦めたとしても、とりあえず「こんなんやりたかった」って公開しておけば優しい人たちが代わって実装してくれるかもしれません。

今年こそ(私以外の人の手による)クリスマスRubyが一つでも公開されることを願っています。