トップ 追記 RSS feed

継続にっき

2004|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|12|
2006|01|03|05|06|08|09|10|12|
2007|01|02|03|05|07|12|
2008|10|
2009|01|05|12|
2010|04|05|11|
2011|01|09|12|
2012|02|

2012-02-04 (Sat)

))) ScalaっぽいパターンマッチをRubyで実装する

例によって思いつきドリブン実装。var @ patternをpattern :: varで表現していることを除けば見た目はそれなりになった感がある、ような。

require 'match'

class EMail
  def self.unapply(value)
    value.to_s.split(/@/).tap {|parts| raise PatternNotMatchError.new unless parts.length == 2}
  end
end

match([1, "foo-bar@example.com"]) {
  pattern(Array.(i, EMail.(/(\w+)-(\w+)/.(firstname, 'bar') :: name, domain) :: mail)) {
    p [i, firstname, name, domain, mail] # => [1, "foo", "foo-bar", "example.com", "foo-bar@example.com"]
  }
}

パターンマッチは時々欲しくなるのでRuby 3.0あたりで言語仕様に取り込まれないかなぁと思うんだけど、あまりパターンマッチについて議論されているところを見た記憶がない。 Refinementsが入ればライブラリレベルでがんばれるようになるんだろうか。


2011-12-12 (Mon)

))) ruby-trunk-changesをgitから参照する

Rubyの開発に興味がある人にはおなじみだと思いますが、PB memoにてruby-trunk-changesというものが公開されています。コミッタのnagachikaさんがCRubyの変更内容についてコミット単位で解説をされているという非常に参考になるコンテンツですが、どうせならWebからだけでなくgitからも参照したいと思ってgit notes用のデータを用意してみました。

コミットの差分とその背景がまとめて見られるようになって便利です。

$ git log -p
commit 09c399b68e6162b68e52dfd22763408def2f813e
Author: naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
Date:   Wed Dec 7 22:13:04 2011 +0000

    It is fixed in FreeBSD 9.0 RC3, not RC2.

    So skip until it is released.

    git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33973 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Notes (ruby-trunk-changes):
    r33967 で FreeBSD でこけるテストの skip 条件を緩和していましたが、まだ Release
    Candidate が出ているだけで RC3 から修正済みなので FreeBSD 9.0 がリリースされる
    まではスキップするようにしています。

diff --git a/test/-ext-/wait_for_single_fd/test_wait_for_single_fd.rb b/test/-ext-/wait_for_single_fd/test_wait_for_single_fd.rb
index 72914f0..64c05c1 100644
--- a/test/-ext-/wait_for_single_fd/test_wait_for_single_fd.rb
+++ b/test/-ext-/wait_for_single_fd/test_wait_for_single_fd.rb
@@ -23,7 +23,7 @@ class TestWaitForSingleFD < Test::Unit::TestCase
   def test_wait_for_invalid_fd
     # FreeBSD 8.2 or prior sticks this
     # http://redmine.ruby-lang.org/issues/5524
-    skip if /freebsd[1-8]/ =~ RUBY_PLATFORM
+    skip if /freebsd[1-9]/ =~ RUBY_PLATFORM
     with_pipe do |r,w|
       wfd = w.fileno
       w.close

使い方ですが、CRubyのgitリポジトリ(git://github.com/ruby/ruby.git)をcloneしてきた後.git/configに以下の設定を加えます。

[core]
        # デフォルトで参照するnotes。この設定はせずに"git log --show-notes=ruby-trunk-changes"とする方法もあり。
        notesRef = refs/notes/ruby-trunk-changes
[remote "k-tsj"]
        # notesのfetch先。
        fetch = +refs/notes/*:refs/notes/*
        url = git://github.com/k-tsj/ruby.git

設定後、k-tsjをfetchすれば準備は完了です。

なお、nagachikaさんに許可をいただいたのでgithub上のデータは今後定期的に更新していく予定です。 参考までに更新用スクリプトへのリンクを張っておきます。


2011-09-18 (Sun)

))) Rubyの例外終了時に自動でREPLを起動する

Rubyが例外を吐いて終了する際に、例外発生時点の環境で自動でREPLが起動するようになっていればデバッグ楽だよなぁと思っていたのだけど、 1つ実装方法をひらめいたのでライブラリを作ってみた。

これを使うと以下のようなことが出来るようになる。

$ ruby -rdebug-exception -e '
  def f(i)
     raise "test"
  end

  f(0)
'
RuntimeError: test
        from -e:3:in `f'
        from -e:6:in `<main>'
irb#1(main):001:0> i
=> 0

debug.rbやruby-debugと比較したときのこのライブラリのメリットは以下の2点*1

  • キャッチする例外をあらかじめ指定したり、ソースコードを変更しておいたりする必要がなく、ライブラリをロードしておくだけで使えるので楽。
  • 例外オブジェクトが生成されない限りオーバーヘッドはないので高速*2。開発時は常時requireしておいても問題ないぐらいのパフォーマンスは出るはず。

ただ、今のRubyはデバッグ用に使えるAPIがあまり整備されていないのでこの実装も機能制限付きな部分がある。 (例えばinitializeを再定義しているようなユーザ定義例外クラスを使うとうまく動かない)

2012/04までにこのあたりを何とかするという話も出ているので、 それにあわせてもう少しまともに作っておくと便利かな。

*1 ruby-debugはしっかり使ったことないので外しているかも。

*2 StandardErrorのinitializeの中で直近のbindingを保存させるようにするというのが基本的な考え方。

本日のツッコミ(全3件) [ツッコミを入れる]

_ なかだ [どういう機能がほしいかあげてもらえると助かります。]

_ k_tsj [この機能に必要なものに絞って話をすると、[ruby-dev:44024]他で議論されているAPIがあればよさそうです..]

_ k_tsj [む、今更気づいたけどこのアプローチだと例外の生成とraiseを全く無関係の場所で行ってしまうと対応できないな。]


2004|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|12|
2006|01|03|05|06|08|09|10|12|
2007|01|02|03|05|07|12|
2008|10|
2009|01|05|12|
2010|04|05|11|
2011|01|09|12|
2012|02|
トップ 追記 RSS feed