[#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:38431] Re: Enumerable#gather_each
In article <8763g9qx9s.fsf@fsij.org>,
Tanaka Akira <akr@fsij.org> writes:
> gather も Yielder を使う形にすれば、gather_each をなくすこと
> は可能だと思います。
そういう形で作ってみたのでつけておきます。
ふと思いついたので、gather には chunk_by という名前もつけてあります。
* Enumerable#chunk_by
* Enumerable#gather
* Enumerable#slice_before
% svn diff --diff-cmd diff -x '-u -p'
Index: enum.c
===================================================================
--- enum.c (revision 23381)
+++ enum.c (working copy)
@@ -1793,6 +1793,170 @@ enum_cycle(int argc, VALUE *argv, VALUE
return Qnil; /* not reached */
}
+struct chunk_by_arg {
+ VALUE categorize;
+ VALUE prev_value;
+ VALUE prev_elts;
+ VALUE yielder;
+};
+
+static VALUE
+chunk_by_ii(VALUE i, VALUE _argp, int argc, VALUE *argv)
+{
+ struct chunk_by_arg *argp = (struct chunk_by_arg *)_argp;
+ VALUE v;
+ VALUE singleton = ID2SYM(rb_intern("_singleton"));
+ VALUE separator = ID2SYM(rb_intern("_separator"));
+
+ ENUM_WANT_SVALUE();
+
+ v = rb_funcall(argp->categorize, rb_intern("call"), 1, i);
+
+ if (v == singleton) {
+ if (!NIL_P(argp->prev_value)) {
+ rb_funcall(argp->yielder, rb_intern("<<"), 1, argp->prev_elts);
+ argp->prev_value = argp->prev_elts = Qnil;
+ }
+ rb_funcall(argp->yielder, rb_intern("<<"), 1, rb_ary_new3(1, i));
+ }
+ else if (!RTEST(v) || v == separator) {
+ if (!NIL_P(argp->prev_value)) {
+ rb_funcall(argp->yielder, rb_intern("<<"), 1, argp->prev_elts);
+ argp->prev_value = argp->prev_elts = Qnil;
+ }
+ }
+ else if (SYMBOL_P(v) && rb_id2name(SYM2ID(v))[0] == '_') {
+ rb_raise(rb_eRuntimeError, "symbol begins with an underscore is reserved");
+ }
+ else {
+ if (NIL_P(argp->prev_value)) {
+ argp->prev_value = v;
+ argp->prev_elts = rb_ary_new3(1, i);
+ }
+ else {
+ if (rb_equal(argp->prev_value, v)) {
+ rb_ary_push(argp->prev_elts, i);
+ }
+ else {
+ rb_funcall(argp->yielder, rb_intern("<<"), 1, argp->prev_elts);
+ argp->prev_value = v;
+ argp->prev_elts = rb_ary_new3(1, i);
+ }
+ }
+ }
+ return Qnil;
+}
+
+static VALUE
+chunk_by_i(VALUE yielder, VALUE enumerator, int argc, VALUE *argv)
+{
+ VALUE enumerable;
+ struct chunk_by_arg arg;
+
+ enumerable = rb_ivar_get(enumerator, rb_intern("chunk_by_enumerable"));
+ arg.categorize = rb_ivar_get(enumerator, rb_intern("chunk_by_categorize"));
+ arg.prev_value = Qnil;
+ arg.prev_elts = Qnil;
+ arg.yielder = yielder;
+
+ rb_block_call(enumerable, id_each, 0, 0, chunk_by_ii, (VALUE)&arg);
+ if (!NIL_P(arg.prev_elts))
+ rb_funcall(arg.yielder, rb_intern("<<"), 1, arg.prev_elts);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.chunk_by {|elt| ... } => enumerator
+ *
+ * Creates an enumerator for iterating chunked elements of _enum_.
+ *
+ * This method gathers consecutive elements which
+ * the blocks returns a same value.
+ *
+ * The following values has special meaning:
+ * - nil, false and :_separator specifies that gathered elements is not yielded.
+ * - :_singleton specifies the element should be gathered only itself.
+ *
+ * Other symbols which begins an underscore may be used in future.
+ *
+ * (1..10).chunk_by {|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.chunk_by {|line| /\A\s/ =~ line }.each {|lines| pp lines }
+ *
+ */
+static VALUE
+enum_chunk_by(VALUE enumerable)
+{
+ VALUE enumerator = rb_obj_alloc(rb_cEnumerator);
+ rb_ivar_set(enumerator, rb_intern("chunk_by_enumerable"), enumerable);
+ rb_ivar_set(enumerator, rb_intern("chunk_by_categorize"), rb_block_proc());
+ rb_block_call(enumerator, rb_intern("initialize"), 0, 0, chunk_by_i, enumerator);
+ return enumerator;
+}
+
+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 = rb_obj_alloc(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;
+}
+
/*
* The <code>Enumerable</code> mixin provides collection classes with
* several traversal and searching methods, and with the ability to
@@ -1852,6 +2016,9 @@ 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", enum_chunk_by, 0);
+ rb_define_method(rb_mEnumerable, "chunk_by", enum_chunk_by, 0);
+ rb_define_method(rb_mEnumerable, "slice_before", enum_slice_before, 0);
id_eqq = rb_intern("===");
id_each = rb_intern("each");
--
[田中 哲][たなか あきら][Tanaka Akira]