例によって思いつきドリブン実装。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が入ればライブラリレベルでがんばれるようになるんだろうか。
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上のデータは今後定期的に更新していく予定です。 参考までに更新用スクリプトへのリンクを張っておきます。
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。
ただ、今のRubyはデバッグ用に使えるAPIがあまり整備されていないのでこの実装も機能制限付きな部分がある。 (例えばinitializeを再定義しているようなユーザ定義例外クラスを使うとうまく動かない)
2012/04までにこのあたりを何とかするという話も出ているので、 それにあわせてもう少しまともに作っておくと便利かな。
_ なかだ [どういう機能がほしいかあげてもらえると助かります。]
_ k_tsj [この機能に必要なものに絞って話をすると、[ruby-dev:44024]他で議論されているAPIがあればよさそうです..]
_ k_tsj [む、今更気づいたけどこのアプローチだと例外の生成とraiseを全く無関係の場所で行ってしまうと対応できないな。]