[#35789] [Ruby 1.9 - Bug #407] (Open) String#<< — Shyouhei Urabe <redmine@...>

チケット #407 が報告されました。 (by Shyouhei Urabe)

13 messages 2008/08/06

[#35845] [Bug #437] test_strftime(TestTime) fails on Solaris — Shugo Maeda <redmine@...>

Bug #437: test_strftime(TestTime) fails on Solaris

24 messages 2008/08/13
[#35855] Re: [Bug #437] test_strftime(TestTime) fails on Solaris — "Shugo Maeda" <shugo@...> 2008/08/15

前田です。

[#35856] Re: [Bug #437] test_strftime(TestTime) fails on Solaris — SATOH Fumiyasu <fumiyas@...> 2008/08/15

さとうふみやす @ OSS テクノロジです。

[#35857] Re: [Bug #437] test_strftime(TestTime) fails on Solaris — Yukihiro Matsumoto <matz@...> 2008/08/15

まつもと ゆきひろです

[#35870] Re: [Bug #437] test_strftime(TestTime) fails on Solaris — "Shugo Maeda" <shugo@...> 2008/08/18

前田です。

[#35863] Refactoring of enumerating prime numbers — "Yugui (Yuki Sonoda)" <yugui@...>

Yuguiです。

20 messages 2008/08/16
[#35865] Re: Refactoring of enumerating prime numbers — keiju@... (keiju ISHITSUKA) 2008/08/17

けいじゅ@いしつかです.

[#35867] Re: Refactoring of enumerating prime numbers — "Yugui (Yuki Sonoda)" <yugui@...> 2008/08/17

Yuguiです。

[#35875] Re: Refactoring of enumerating prime numbers — keiju@... (keiju ISHITSUKA) 2008/08/19

けいじゅ@いしつかです.

[#35877] Re: Refactoring of enumerating prime numbers — Nobuyoshi Nakada <nobu@...> 2008/08/19

なかだです。

[#35882] Re: Refactoring of enumerating prime numbers — keiju@... (石塚圭樹) 2008/08/20

けいじゅ@いしつかです.

[#35904] [Feature:1.9] pack format 'm' based on RFC 4648 — "Yusuke ENDOH" <mame@...>

遠藤です。

14 messages 2008/08/21
[#36442] [Feature #471] pack format 'm' based on RFC 4648 — Yuki Sonoda <redmine@...> 2008/09/22

チケット #471 が更新されました。 (by Yuki Sonoda)

[#35906] %N for Time#strftime — "Shugo Maeda" <shugo@...>

前田です。

13 messages 2008/08/21

[#35986] 1.9と1.8で、delegateのインスタンスのクラス名の違う — Fujioka <fuj@...>

xibbarこと藤岡です。

17 messages 2008/08/26
[#35987] Re: 1.9と1.8で、delegateのインスタンスのクラス名の違う — Yukihiro Matsumoto <matz@...> 2008/08/26

まつもと ゆきひろです

[#35991] Re: 1.9と1.8で、delegateのインスタンスのクラス名の違う — keiju@... (石塚圭樹) 2008/08/26

けいじゅ@いしつかです.

[#35994] Re: 1.9と1.8で、delegateのインスタンスのクラス名の違う — Fujioka <fuj@...> 2008/08/27

藤岡です。

[#35998] Re: 1.9と1.8で、delegateのインスタンスのクラス名の違う — keiju@... (石塚圭樹) 2008/08/27

けいじゅ@いしつかです.

[#36066] Numeric#scalar? — Tadayoshi Funaba <tadf@...>

1.9 の Numeric#scalar? について、適当でないのでは (real? などのほうがい

24 messages 2008/08/31
[#36069] Re: Numeric#scalar? — Shin-ichiro HARA <sinara@...> 2008/08/31

原です。

[#36104] Re: Numeric#scalar? — Tadayoshi Funaba <tadf@...> 2008/09/02

> やはり、scalar? はずれているんじゃないかな。real? の方がいい

[#36122] Re: Numeric#scalar? — Shin-ichiro HARA <sinara@...> 2008/09/03

原です。

[#36133] Re: Numeric#scalar? — Tadayoshi Funaba <tadf@...> 2008/09/03

> ここで、scalar? を疑問視する理由を復習すると、たとえば、「複

[#36173] Re: Numeric#scalar? — Tadayoshi Funaba <tadf@...> 2008/09/05

1.9.1 までに時間がないので scalar? だけ何とかしたいと思っていましたが、

[#36183] Re: Numeric#scalar? — "Shugo Maeda" <shugo@...> 2008/09/06

前田です。

[#36186] Re: Numeric#scalar? — Shin-ichiro HARA <sinara@...> 2008/09/06

原です。

[ruby-dev:35903] Enumerable object from a block

From: "Akinori MUSHA" <knu@...>
Date: 2008-08-21 13:19:15 UTC
List: ruby-dev #35903
 ブロックで簡単に Enumerable なオブジェクトを作れる機能を追加
しようと思いますが、どうでしょうか。

 いちいちクラスを作ったり、 extend(Enumerable) して特異メソッド
each を定義したりしなくて済みます。

    # フィボナッチ数列(n>=1)
    fib = Enumerator.new { |y|
      a = b = 1
      loop {
        y << a
        a, b = b, a + b
      }
    }

    p fib.take(10) #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]


 元は Ruby 1.8 の generator.rb についていたおまけ機能ですが、
手軽に無限リストや柔軟な繰り返しを定義できるので便利です。

--
Akinori MUSHA / http://akinori.org/

Index: enumerator.c
===================================================================
--- enumerator.c	(revision 18754)
+++ enumerator.c	(working copy)
@@ -35,6 +35,22 @@ struct enumerator {
     VALUE no_next;
 };

+static VALUE rb_cGenerator, rb_cYielder;
+
+struct generator {
+    VALUE proc;
+};
+
+struct yielder {
+    VALUE proc;
+};
+
+static VALUE generator_allocate(VALUE klass);
+static VALUE generator_init(VALUE obj, VALUE proc);
+
+/*
+ * Enumerator
+ */
 static void
 enumerator_mark(void *p)
 {
@@ -242,25 +258,53 @@ enumerator_init(VALUE enum_obj, VALUE ob
 /*
  *  call-seq:
  *    Enumerator.new(obj, method = :each, *args)
+ *    Enumerator.new { |y| ... }
  *
  *  Creates a new Enumerator object, which is to be used as an
- *  Enumerable object using the given object's given method with the
- *  given arguments.
+ *  Enumerable object iterating in a given way.
  *
- *  Use of this method is discouraged.  Use Kernel#enum_for() instead.
+ *  In the first form, a generated Enumerator iterates over the given
+ *  object using the given method with the given arguments passed.
+ *  Use of this form is discouraged.  Use Kernel#enum_for(), alias
+ *  to_enum, instead.
+ *
+ *    e = Enumerator.new(ObjectSpace, :each_object)
+ *        #-> ObjectSpace.enum_for(:each_object)
+ *
+ *    e.select { |obj| obj.is_a?(Class) }  #=> array of all classes
+ *
+ *  In the second form, iteration is defined by the given block, in
+ *  which a "yielder" object given as block parameter can be used to
+ *  yield a value by calling the +yield+ method, alias +<<+.
+ *
+ *    fib = Enumerator.new { |y|
+ *      a = b = 1
+ *      loop {
+ *        y << a
+ *        a, b = b, a + b
+ *      }
+ *    }
+ *
+ *    p fib.take(10) #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
  */
 static VALUE
 enumerator_initialize(int argc, VALUE *argv, VALUE obj)
 {
     VALUE recv, meth = sym_each;

-    if (argc == 0)
-	rb_raise(rb_eArgError, "wrong number of argument (0 for 1)");
-    recv = *argv++;
-    if (--argc) {
-	meth = *argv++;
-	--argc;
+    if (argc == 0) {
+	if (!rb_block_given_p())
+	    rb_raise(rb_eArgError, "wrong number of argument (0 for 1+)");
+
+	recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc());
+    } else {
+	recv = *argv++;
+	if (--argc) {
+	    meth = *argv++;
+	    --argc;
+	}
     }
+
     return enumerator_init(obj, recv, meth, argc, argv);
 }

@@ -471,6 +515,217 @@ enumerator_rewind(VALUE obj)
     return obj;
 }

+/*
+ * Yielder
+ */
+static void
+yielder_mark(void *p)
+{
+    struct yielder *ptr = p;
+    rb_gc_mark(ptr->proc);
+}
+
+static struct yielder *
+yielder_ptr(VALUE obj)
+{
+    struct yielder *ptr;
+
+    Data_Get_Struct(obj, struct yielder, ptr);
+    if (RDATA(obj)->dmark != yielder_mark) {
+	rb_raise(rb_eTypeError,
+		 "wrong argument type %s (expected %s)",
+		 rb_obj_classname(obj), rb_class2name(rb_cYielder));
+    }
+    if (!ptr || ptr->proc == Qundef) {
+	rb_raise(rb_eArgError, "uninitialized yielder");
+    }
+    return ptr;
+}
+
+/* :nodoc: */
+static VALUE
+yielder_allocate(VALUE klass)
+{
+    struct yielder *ptr;
+    VALUE obj;
+
+    obj = Data_Make_Struct(klass, struct yielder, yielder_mark, -1, ptr);
+    ptr->proc = Qundef;
+
+    return obj;
+}
+
+static VALUE
+yielder_init(VALUE obj, VALUE proc)
+{
+    struct yielder *ptr;
+
+    Data_Get_Struct(obj, struct yielder, ptr);
+
+    if (!ptr) {
+	rb_raise(rb_eArgError, "unallocated yielder");
+    }
+
+    ptr->proc = proc;
+
+    return obj;
+}
+
+/* :nodoc: */
+static VALUE
+yielder_initialize(VALUE obj)
+{
+    rb_need_block();
+
+    return yielder_init(obj, rb_block_proc());
+}
+
+/* :nodoc: */
+static VALUE
+yielder_yield(VALUE obj, VALUE args)
+{
+    struct yielder *ptr = yielder_ptr(obj);
+
+    rb_proc_call(ptr->proc, args);
+
+    return obj;
+}
+
+static VALUE
+yielder_new_i(VALUE dummy)
+{
+    return yielder_init(yielder_allocate(rb_cYielder), rb_block_proc());
+}
+
+static VALUE
+yielder_yield_i(VALUE obj, VALUE memo, int argc, VALUE *argv)
+{
+    return rb_yield(obj);
+}
+
+static VALUE
+yielder_new(void)
+{
+    return rb_iterate(yielder_new_i, (VALUE)0, yielder_yield_i, (VALUE)0);
+}
+
+/*
+ * Generator
+ */
+static void
+generator_mark(void *p)
+{
+    struct generator *ptr = p;
+    rb_gc_mark(ptr->proc);
+}
+
+static struct generator *
+generator_ptr(VALUE obj)
+{
+    struct generator *ptr;
+
+    Data_Get_Struct(obj, struct generator, ptr);
+    if (RDATA(obj)->dmark != generator_mark) {
+	rb_raise(rb_eTypeError,
+		 "wrong argument type %s (expected %s)",
+		 rb_obj_classname(obj), rb_class2name(rb_cGenerator));
+    }
+    if (!ptr || ptr->proc == Qundef) {
+	rb_raise(rb_eArgError, "uninitialized generator");
+    }
+    return ptr;
+}
+
+/* :nodoc: */
+static VALUE
+generator_allocate(VALUE klass)
+{
+    struct generator *ptr;
+    VALUE obj;
+
+    obj = Data_Make_Struct(klass, struct generator, generator_mark, -1, ptr);
+    ptr->proc = Qundef;
+
+    return obj;
+}
+
+static VALUE
+generator_init(VALUE obj, VALUE proc)
+{
+    struct generator *ptr;
+
+    Data_Get_Struct(obj, struct generator, ptr);
+
+    if (!ptr) {
+	rb_raise(rb_eArgError, "unallocated generator");
+    }
+
+    ptr->proc = proc;
+
+    return obj;
+}
+
+VALUE rb_obj_is_proc(VALUE proc);
+
+/* :nodoc: */
+static VALUE
+generator_initialize(int argc, VALUE *argv, VALUE obj)
+{
+    VALUE proc;
+
+    if (argc == 0) {
+	rb_need_block();
+
+	proc = rb_block_proc();
+    } else {
+	rb_scan_args(argc, argv, "1", &proc);
+
+	if (!rb_obj_is_proc(proc))
+	    rb_raise(rb_eTypeError,
+		     "wrong argument type %s (expected Proc)",
+		     rb_obj_classname(proc));
+
+	if (rb_block_given_p()) {
+	    rb_warn("given block not used");
+	}
+    }
+
+    return generator_init(obj, proc);
+}
+
+/* :nodoc: */
+static VALUE
+generator_init_copy(VALUE obj, VALUE orig)
+{
+    struct generator *ptr0, *ptr1;
+
+    ptr0 = generator_ptr(orig);
+
+    Data_Get_Struct(obj, struct generator, ptr1);
+
+    if (!ptr1) {
+	rb_raise(rb_eArgError, "unallocated generator");
+    }
+
+    ptr1->proc = ptr0->proc;
+
+    return obj;
+}
+
+/* :nodoc: */
+static VALUE
+generator_each(VALUE obj)
+{
+    struct generator *ptr = generator_ptr(obj);
+    VALUE yielder;
+
+    yielder = yielder_new();
+
+    rb_proc_call(ptr->proc, rb_ary_new3(1, yielder));
+
+    return obj;
+}
+
 void
 Init_Enumerator(void)
 {
@@ -497,9 +752,24 @@ Init_Enumerator(void)
     rb_define_method(rb_cEnumerator, "next", enumerator_next, 0);
     rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);

-    rb_eStopIteration   = rb_define_class("StopIteration", rb_eIndexError);
+    rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError);

-    sym_each	 	= ID2SYM(rb_intern("each"));
+    /* Generator */
+    rb_cGenerator = rb_define_class_under(rb_cEnumerator, "Generator", rb_cObject);
+    rb_include_module(rb_cGenerator, rb_mEnumerable);
+    rb_define_alloc_func(rb_cGenerator, generator_allocate);
+    rb_define_method(rb_cGenerator, "initialize", generator_initialize, -1);
+    rb_define_method(rb_cGenerator, "initialize_copy", generator_init_copy, 1);
+    rb_define_method(rb_cGenerator, "each", generator_each, 0);
+
+    /* Yielder */
+    rb_cYielder = rb_define_class_under(rb_cEnumerator, "Yielder", rb_cObject);
+    rb_define_alloc_func(rb_cYielder, yielder_allocate);
+    rb_define_method(rb_cYielder, "initialize", yielder_initialize, 0);
+    rb_define_method(rb_cYielder, "yield", yielder_yield, -2);
+    rb_define_method(rb_cYielder, "<<", yielder_yield, -2);
+
+    sym_each = ID2SYM(rb_intern("each"));

     rb_provide("enumerator.so");	/* for backward compatibility */
 }

In This Thread

Prev Next