[#38371] Re: [ruby-cvs:30538] Ruby:r23320 (trunk): * lib/set.rb (SortedSet#add): Do not let an uncomparable object — "Yugui (Yuki Sonoda)" <yugui@...>
Yuguiです。
At Mon, 4 May 2009 23:44:22 +0900,
遠藤です。
At Fri, 8 May 2009 02:00:10 +0900,
[#38372] making install-sh more descriptive — "Yugui (Yuki Sonoda)" <yugui@...>
install-shが空になって久しい(r520)です。
[#38382] [Bug #1442] indentation check and coverage for toplevel do not work — Yusuke Endoh <redmine@...>
Bug #1442: indentation check and coverage for toplevel do not work
[#38390] [Bug:1.8] Tempfile and extended Enumerable — Tanaka Akira <akr@...>
1.8.8dev で、以下のように、Enumerable に each2 を定義し、
[#38392] Enumerable#gather_each — Tanaka Akira <akr@...>
ときに、複数行をまとめて扱いたいことがあります。
ujihisaと申します。
まつもと ゆきひろです
At Sun, 10 May 2009 06:00:08 +0900,
In article <E1M2t0u-0000Aa-Sd@x61.netlab.jp>,
まつもと ゆきひろです
In article <E1M4oSd-00005c-WB@x61.netlab.jp>,
In article <873ab3531u.fsf@fsij.org>,
まつもと ゆきひろです
At Sat, 9 May 2009 15:30:20 +0900,
In article <86r5yy2nrg.knu@iDaemons.org>,
At Sun, 10 May 2009 10:08:47 +0900,
In article <86ocu132gq.knu@iDaemons.org>,
At Sun, 10 May 2009 15:57:33 +0900,
In article <86my9l2tts.knu@iDaemons.org>,
Haskell の groupBy と Python の groupby が似ている、という話
遠藤です。
In article <e0b1e5700905140800y6d701c6fj731a59ffd83b9d79@mail.gmail.com>,
[#38423] longlife gc — Narihiro Nakamura <authornari@...>
nariと申します.
[#38446] [Bug:1.9] exact Time and inexact Time — Yusuke ENDOH <mame@...>
遠藤です。
In article <e0b1e5700905132145i32bed2f0y80faef19c119824f@mail.gmail.com>,
遠藤です。
[#38463] SQLiteライブラリ — "NARUSE, Yui" <naruse@...>
成瀬です。
[#38486] [Bug #1483] some commands installed without program-suffix — Kazuhiro NISHIYAMA <redmine@...>
Bug #1483: some commands installed without program-suffix
[#38493] [Feature:trunk] enhancement of Array#drop — "U.Nakamura" <usa@...>
こんにちは、なかむら(う)です。
まつもと ゆきひろです
こんにちは、なかむら(う)です。
[#38518] [Bug:1.9] Enumerator.new { }.take(1).inject(&:+) causes stack overflow — Yusuke ENDOH <mame@...>
遠藤です。
[#38524] [Bug #1503] -Kuをつけた時、/[#{s}]/n と Regexp.new("[#{s}]",nil,"n") で実行結果が異なる — sinnichi eguchi <redmine@...>
Bug #1503: -Kuをつけた時、/[#{s}]/n と Regexp.new("[#{s}]",nil,"n") で実行結果が異なる
[ruby-dev:38418] Re: Enumerable#gather_each
In article <871vqysrru.fsf@fsij.org>,
Tanaka Akira <akr@fsij.org> writes:
> C での実装はまだですが、これからやる予定です。
とりあえず C で実装してみたのでつけておきます。
以下のメソッドを実装してあります。
* Enumerable#gather_each
* Enumerable#gather
* Enumerable#slice_before
slice_before は Yielder を使ってあります。
gather も Yielder を使う形にすれば、gather_each をなくすこと
は可能だと思います。
% svn diff --diff-cmd diff -x '-u -p'
Index: enumerator.c
===================================================================
--- enumerator.c (revision 23381)
+++ enumerator.c (working copy)
@@ -14,6 +14,18 @@
#include "ruby/ruby.h"
+static VALUE
+enum_values_pack(int argc, VALUE *argv)
+{
+ if (argc == 0) return Qnil;
+ if (argc == 1) return argv[0];
+ return rb_ary_new4(argc, argv);
+}
+
+#define ENUM_WANT_SVALUE() do { \
+ i = enum_values_pack(argc, argv); \
+} while (0)
+
/*
* Document-class: Enumerator
*
@@ -45,6 +57,7 @@ struct yielder {
VALUE proc;
};
+static VALUE enumerator_allocate(VALUE klass);
static VALUE generator_allocate(VALUE klass);
static VALUE generator_init(VALUE obj, VALUE proc);
@@ -247,6 +260,61 @@ enum_each_with_object(VALUE obj, VALUE m
return memo;
}
+struct slice_before_arg {
+ VALUE separator_p;
+ VALUE prev_elts;
+ VALUE yielder;
+};
+
+static VALUE
+slice_before_ii(VALUE i, VALUE _argp, int argc, VALUE *argv)
+{
+ struct slice_before_arg *argp = (struct slice_before_arg *)_argp;
+
+ ENUM_WANT_SVALUE();
+
+ if (RTEST(rb_funcall(argp->separator_p, rb_intern("call"), 1, i))) {
+ if (!NIL_P(argp->prev_elts))
+ rb_funcall(argp->yielder, rb_intern("<<"), 1, argp->prev_elts);
+ argp->prev_elts = rb_ary_new3(1, i);
+ }
+ else {
+ if (NIL_P(argp->prev_elts))
+ argp->prev_elts = rb_ary_new3(1, i);
+ else
+ rb_ary_push(argp->prev_elts, i);
+ }
+
+ return Qnil;
+}
+
+static VALUE
+slice_before_i(VALUE yielder, VALUE enumerator, int argc, VALUE *argv)
+{
+ VALUE enumerable;
+ struct slice_before_arg arg;
+
+ enumerable = rb_ivar_get(enumerator, rb_intern("slice_before_enumerable"));
+ arg.separator_p = rb_ivar_get(enumerator, rb_intern("slice_before_separator_p"));
+ arg.prev_elts = Qnil;
+ arg.yielder = yielder;
+
+ rb_block_call(enumerable, id_each, 0, 0, slice_before_ii, (VALUE)&arg);
+ if (!NIL_P(arg.prev_elts))
+ rb_funcall(arg.yielder, rb_intern("<<"), 1, arg.prev_elts);
+ return Qnil;
+}
+
+static VALUE
+enum_slice_before(VALUE enumerable)
+{
+ VALUE enumerator = enumerator_allocate(rb_cEnumerator);
+ rb_ivar_set(enumerator, rb_intern("slice_before_enumerable"), enumerable);
+ rb_ivar_set(enumerator, rb_intern("slice_before_separator_p"), rb_block_proc());
+ rb_block_call(enumerator, rb_intern("initialize"), 0, 0, slice_before_i, enumerator);
+ return enumerator;
+}
+
static VALUE
enumerator_allocate(VALUE klass)
{
@@ -862,6 +930,8 @@ Init_Enumerator(void)
rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
rb_define_method(rb_mEnumerable, "each_with_object", enum_each_with_object, 1);
+ rb_define_method(rb_mEnumerable, "slice_before", enum_slice_before, 0);
+
rb_cEnumerator = rb_define_class("Enumerator", rb_cObject);
rb_include_module(rb_cEnumerator, rb_mEnumerable);
Index: enum.c
===================================================================
--- enum.c (revision 23381)
+++ enum.c (working copy)
@@ -1793,6 +1793,141 @@ enum_cycle(int argc, VALUE *argv, VALUE
return Qnil; /* not reached */
}
+struct gather_each_st {
+ VALUE arg;
+ VALUE prev_value;
+ VALUE prev_elts;
+};
+
+static VALUE
+gather_each_i(VALUE i, VALUE _state, int argc, VALUE *argv)
+{
+ struct gather_each_st *statep = (struct gather_each_st *)_state;
+ VALUE v;
+ VALUE singleton, reject;
+
+ ENUM_WANT_SVALUE();
+
+ v = rb_funcall(statep->arg, rb_intern("call"), 1, i);
+
+ singleton = ID2SYM(rb_intern("singleton"));
+ reject = ID2SYM(rb_intern("reject"));
+
+ if (v == singleton) {
+ if (!NIL_P(statep->prev_value)) {
+ rb_yield(statep->prev_elts);
+ statep->prev_value = statep->prev_elts = Qnil;
+ }
+ rb_yield(rb_ary_new3(1, i));
+ }
+ else if (!RTEST(v) || v == reject) {
+ if (!NIL_P(statep->prev_value)) {
+ rb_yield(statep->prev_elts);
+ statep->prev_value = statep->prev_elts = Qnil;
+ }
+ }
+ else {
+ if (NIL_P(statep->prev_value)) {
+ statep->prev_value = v;
+ statep->prev_elts = rb_ary_new3(1, i);
+ }
+ else {
+ if (rb_equal(statep->prev_value, v)) {
+ rb_ary_push(statep->prev_elts, i);
+ }
+ else {
+ rb_yield(statep->prev_elts);
+ statep->prev_value = v;
+ statep->prev_elts = rb_ary_new3(1, i);
+ }
+ }
+ }
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.gather_each(arg) {|ary| ... } => nil
+ * enum.gather_each(arg) => enumerator
+ *
+ * Iterates for each gathered elements of _enum_.
+ *
+ * This method gathers consecutive elements which
+ * _arg_.call(_element_) returns a same value.
+ *
+ * The following values has special meaning:
+ * - nil, false and :reject specifies that gathered elements is not yielded.
+ * - :singleton specifies the element should be gathered only itself.
+ *
+ * The gathered element is yielded as an array.
+ *
+ * If the block is not given, an enumerator is returned.
+ *
+ * (1..10).gather_each(lambda {|n| n & 2 }) {|a| p a }
+ * #=> [1] # 1 & 2 = 0
+ * # [2, 3] # 2 & 2 = 3 & 2 = 1
+ * # [4, 5] # 4 & 2 = 5 & 2 = 0
+ * # [6, 7] # 6 & 2 = 7 & 2 = 1
+ * # [8, 9] # 8 & 2 = 9 & 2 = 0
+ * # [10] # 10 & 2 = 1
+ *
+ * # gather indented blocks.
+ * io.gather_each(lambda {|line| /\A\s/ =~ line }) {|lines| pp lines }
+ *
+ */
+static VALUE
+enum_gather_each(int argc, VALUE *argv, VALUE self)
+{
+ struct gather_each_st state;
+
+ rb_scan_args(argc, argv, "01", &state.arg);
+
+ RETURN_ENUMERATOR(self, argc, argv);
+
+ state.prev_value = Qnil;
+ state.prev_elts = Qnil;
+
+ rb_block_call(self, id_each, 0, 0, gather_each_i, (VALUE)&state);
+
+ if (state.prev_value != Qnil)
+ rb_yield(state.prev_elts);
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.gather {|elt| ... } => enumerator
+ *
+ * Creates an enumerator for iterating gathered elements of _enum_.
+ *
+ * This method gathers consecutive elements which
+ * the blocks returns a same value.
+ *
+ * The following values has special meaning:
+ * - nil, false and :reject specifies that gathered elements is not yielded.
+ * - :singleton specifies the element should be gathered only itself.
+ *
+ * (1..10).gather {|n| n & 2 }.each {|a| p a }
+ * #=> [1] # 1 & 2 = 0
+ * # [2, 3] # 2 & 2 = 3 & 2 = 1
+ * # [4, 5] # 4 & 2 = 5 & 2 = 0
+ * # [6, 7] # 6 & 2 = 7 & 2 = 1
+ * # [8, 9] # 8 & 2 = 9 & 2 = 0
+ * # [10] # 10 & 2 = 1
+ *
+ * # gather indented blocks.
+ * io.gather {|line| /\A\s/ =~ line }.each {|lines| pp lines }
+ *
+ */
+static VALUE
+enum_gather(VALUE self)
+{
+ VALUE block = rb_block_proc();
+ return rb_enumeratorize(self, ID2SYM(rb_intern("gather_each")), 1, &block);
+}
+
/*
* The <code>Enumerable</code> mixin provides collection classes with
* several traversal and searching methods, and with the ability to
@@ -1852,6 +1987,8 @@ Init_Enumerable(void)
rb_define_method(rb_mEnumerable, "drop", enum_drop, 1);
rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
+ rb_define_method(rb_mEnumerable, "gather_each", enum_gather_each, -1);
+ rb_define_method(rb_mEnumerable, "gather", enum_gather, 0);
id_eqq = rb_intern("===");
id_each = rb_intern("each");
--
[田中 哲][たなか あきら][Tanaka Akira]