やはりEnumerable#empty?は、汚染無しで可能でした
Enumerable#empty?は、汚染なしに可能かの続き。
Twitterでn0kadaさんから、もっとエレガントな書き方があると教えてもらいました。
(ありがとうございます!>n0kadaさん)
Owner@fam ~ $ /usr/local/ruby-1.8.1/bin/ruby -ve ' p [].any?{true} # => false p [1].any?{true} # => true ' ruby 1.8.1 (2003-12-25) [i386-cygwin] false true Owner@fam ~ $ /usr/local/ruby-1.9.0-2/bin/ruby -ve ' p [].any?{true} # => false p [1].any?{true} # => true ' ruby 1.9.0 (2008-06-20 revision 17482) [i386-cygwin] false true
1.8系以降なら使えるEnumerable#any?を使うという方法。
あれだけ汚いコードを書いていたのがバカらしくなってきてしまいます。
せっかくなので、なんとなく1.4系で動くか試したところ、1.4系にはany?はない模様。
C:\develop\Language\ruby-1.4>ruby -ve 'p [].any?{true}' ruby 1.4.6 (2000-08-16) [i386-mswin32] C:\DOCUME~1\Owner\LOCALS~1\Temp/rba03860:1: undefined method `any?' for []:Array (NameError)
ま、今時1.4系を実用として使っている人は居ないと思うので、今となってはどうでもいい情報ですね。
で、実験的にコレをCにして、現在のtruncである#17885に対するパッチ作成。
--- enum.c (revision 17885) +++ enum.c (working copy) @@ -981,6 +981,37 @@ } static VALUE +enum_empty_func(VALUE result, VALUE *memo) +{ + *memo = Qtrue; + rb_iter_break(); + return Qnil; // never reach +} + +DEFINE_ENUMFUNCS(empty) + +/* + * call-seq: + * enum.empty? => true or false + * + * Passes each element of the collection to the given block. The method + * returns <code>true</code> if the collection members by any value + * is a one or more. + * + * [].empty? #=> true + * [1].empty? #=> false + * [nil, nil].empty? #=> false + */ +static VALUE +enum_empty(VALUE obj) +{ + VALUE result = Qfalse; + + rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? empty_iter_i : empty_i, (VALUE)&result); + return result; +} + +static VALUE min_i(VALUE i, VALUE *memo, int argc, VALUE *argv) { VALUE cmp; @@ -1830,6 +1861,7 @@ rb_define_method(rb_mEnumerable, "any?", enum_any, 0); rb_define_method(rb_mEnumerable, "one?", enum_one, 0); rb_define_method(rb_mEnumerable, "none?", enum_none, 0); + rb_define_method(rb_mEnumerable, "empty?", enum_empty, 0); rb_define_method(rb_mEnumerable, "min", enum_min, 0); rb_define_method(rb_mEnumerable, "max", enum_max, 0); rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
で、こいつをコンパイルして実行。
Owner@fam /usr/local/src/ruby/ruby-trunk/ruby $ ./ruby -ve 'p [].empty?; p [nil].empty?' ruby 1.9.0 (2008-07-16 revision 17885) [i386-cygwin] true false
でも、「それって意味あるの?」と言われると、思考実験の産物なので実用からの要求じゃないってところで、苦しいですね。
ついでに名前もコレでいいのか悩んでしまうところ。(nilの扱いとの関連で)
まぁ、このまま寝かせておきますか。
22:20追記
diffの引数が逆だったので修正しました。