あああ、ぜんぜん連絡断ってないよ俺…… でも気になってしまったので気になりながら書くより書いちゃいます。(意味不明)
「バカが征く」での多段イテレータから抜ける話題ですけど、 それは最下層で block.call を使ってるのがまずいんです。 yield 使うか each(&block) でブロック委譲すれば break で 一気に全部抜けられます。
Proc#call から break すると、その Proc#call だけを抜けます。 yield/&block の場合は、ブロックを生成したところの終わりまで抜けます。
この違いには前に net/http でひっかかったことがあるんですよ。 そのときは HTTP#get のブロックから break できなくなってました。
結論だけ言うと、
ということです。Proc のまま使ってよいのは
だけとしておいたほうがよいでしょう。 また、全面委譲では済まない場合は
def iter( &block ) yield @obj.each(&block) @obj.each(&block) yield end
のように yield と m(&block) を組み合わせます。 これ (&block を使いつつ yield できること) は意外と気付かないかもしんない。
(20:14)
ということは、yield や &block を使うときは break で どこのレベルまで抜けるか予想できないということですね。 必要な後処理があればその都度 ensure で囲まなければならないと。
def iter( &block ) begin _iter(&block) ensure # あとしまつ end end def _iter( &block ) begin _iter0(&block) ensure # あとしまつ end end def _iter0 begin yield ensure あとしまつ end end iter { break # ここから、 } # ちゃんと後始末されてここに抜ける。
yield と ensure で思い出したけど ありとあらゆるジャンプを Ruby レベルから停止させる裏技。
def rb_protect begin yield ensure return end end def main # 何やっても無駄 rb_protect { return } puts 'return stopped' rb_protect { exit(1) } puts 'exit stopped' rb_protect { raise "STOP ME!" } puts 'raise stopped' rb_protect { throw(:jump) } puts 'throw stopped' end main
停止させたジャンプの種類を把握できると dRuby とかで使えそうだけども、 さすがにそこまではできんかった。
(20:51)
Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved.
もし気付かれてなかったらなんなんで、一応。
http://rwiki.jin.gr.jp/cgi-bin/rw-cgi.rb?cmd=view;name=RHG%C6%C9%BD%F1%B2%F1
気付いてませんでした ^^;;;
ありがとうございます。
setup 3.1.3ですが、若干要望が。
* できればshebangを書き換えるのはinstall時にしてほしい
* CVSディレクトリはたどってほしくない
* gsub(/declear/, 'declare')
diff -u2p setup-3.1.3/src/toplevel.rb.orig setup-3.1.3/src/toplevel.rb
--- setup-3.1.3/src/toplevel.rb.orig Fri Dec 6 03:26:35 2002
+++ setup-3.1.3/src/toplevel.rb Wed Jan 22 17:05:14 2003
@@ -13,5 +13,5 @@ class ToplevelInstaller < Installer
def initialize( root )
super nil, {'verbose' => true}, root, '.'
- Installer.declear_toplevel_installer self
+ Installer.declare_toplevel_installer self
end
diff -u2p setup-3.1.3/src/fileop.rb.orig setup-3.1.3/src/fileop.rb
--- setup-3.1.3/src/fileop.rb.orig Fri Dec 6 03:26:35 2002
+++ setup-3.1.3/src/fileop.rb Wed Jan 22 16:53:45 2003
@@ -82,4 +82,32 @@ module FileOperations
end
+ SHEBANG_RE = /\A\#!\s*\S*ruby\S*/
+
+ def install_script( from, dest, mode, prefix = nil )
+ if verbose?
+ $stderr.puts <<MESSAGE
+install #{from} #{dest}"
+set #! line to "\#!#{config('ruby-path')}" for #{dest} ...
+MESSAGE
+ end
+ return if no_harm?
+
+ realdest = prefix + dest if prefix
+ if dir? realdest
+ realdest += '/' + File.basename(from)
+ end
+ str = File.read_all(from)
+ str.sub!(SHEBANG_RE, '#!' + config('ruby-path'))
+ if diff? str, realdest
+ verbose_off {
+ rm_f realdest if File.exist? realdest
+ }
+ File.write realdest, str
+ File.chmod mode, realdest
+
+ File.open(objdir + '/InstalledFiles', 'a') {|f| f.puts realdest }
+ end
+ end
+
def diff?( orig, targ )
return true unless File.exist? targ
@@ -108,7 +136,14 @@ module FileOperations
def all_dirs( dname )
- Dir.open(dname) {|d|
+ dirs = Dir.open(dname) {|d|
return d.find_all {|n| dir? "#{dname}/#{n}" } - %w(. ..)
}
+ if dirs.include?("CVS")
+ d = "#{dname}/CVS"
+ unless %w(Entries Root Repository).find {|n| !File.file?("#{d}/#{n}")}
+ dirs -= "CVS"
+ end
+ end
+ dirs
end
diff -u2p setup-3.1.3/src/base.rb.orig setup-3.1.3/src/base.rb
--- setup-3.1.3/src/base.rb.orig Fri Dec 6 03:26:35 2002
+++ setup-3.1.3/src/base.rb Wed Jan 22 17:04:56 2003
@@ -11,7 +11,7 @@ class Installer
@toplevel = nil
- def self.declear_toplevel_installer( inst )
+ def self.declare_toplevel_installer( inst )
@toplevel and
- raise ArgumentError, 'more than one toplevel installer decleared'
+ raise ArgumentError, 'more than one toplevel installer declared'
@toplevel = inst
end
@@ -169,29 +169,4 @@ class Installer
def setup_dir_bin( relpath )
- all_files(curr_srcdir).each do |fname|
- add_rubypath "#{curr_srcdir}/#{fname}"
- end
- end
-
- SHEBANG_RE = /\A\#!\s*\S*ruby\S*/
-
- def add_rubypath( path )
- $stderr.puts %Q<set #! line to "\#!#{config('ruby-path')}" for #{path} ...> if verbose?
- return if no_harm?
-
- tmpfile = File.basename(path) + '.tmp'
- begin
- File.open(path) {|r|
- File.open(tmpfile, 'w') {|w|
- first = r.gets
- return unless SHEBANG_RE === first # reject '/usr/bin/env ruby'
-
- w.print first.sub(SHEBANG_RE, '#!' + config('ruby-path'))
- w.write r.read
- } }
- mv tmpfile, File.basename(path)
- ensure
- rm_f tmpfile if File.exist? tmpfile
- end
end
@@ -219,5 +194,15 @@ class Installer
def install_dir_bin( rel )
- install_files targfiles, config('bin-dir') + '/' + rel, 0755
+ dest = config('bin-dir') + '/' + rel
+ mode = 0755
+ prefix = @options['install-prefix']
+ mkdir_p dest, prefix
+ targfiles.each do |fname|
+ if /\.rb$/ =~ fname
+ install_script fname, dest + File.basename(fname, '.rb'), mode, prefix
+ else
+ install fname, dest, mode, prefix
+ end
+ end
end