[#28561] Ruby::DL vs Ruby::FFI — Aston <blackapache512-ticket@...>

Ruby.DL and FFI libraries are great for programmers like me who are not internet programmers, but are more interested in scientific and number processing etc.

11 messages 2010/03/08

[#28686] trunk (26947) build fail with msys/mingw/vista — Jon <jon.forums@...>

I get the following build failure when msysgit's "c:\git\cmd" dir is on PATH.

8 messages 2010/03/16

[#28687] [Bug #2973] rb_bug - Segmentation fault - error.c:213 — rudolf gavlas <redmine@...>

Bug #2973: rb_bug - Segmentation fault - error.c:213

10 messages 2010/03/16

[#28735] [Bug #2982] Ruby tries to link with both openssl and readline — Lucas Nussbaum <redmine@...>

Bug #2982: Ruby tries to link with both openssl and readline

16 messages 2010/03/18

[#28736] [Bug #2983] Ruby (GPLv2 only) tries to link to with readline (now GPLv3) — Lucas Nussbaum <redmine@...>

Bug #2983: Ruby (GPLv2 only) tries to link to with readline (now GPLv3)

10 messages 2010/03/18

[#28907] [Bug #3000] Open SSL Segfaults — Christian Höltje <redmine@...>

Bug #3000: Open SSL Segfaults

19 messages 2010/03/23

[#28924] [Bug #3005] Ruby core dump - [BUG] rb_sys_fail() - errno == 0 — Sebastian YEPES <redmine@...>

Bug #3005: Ruby core dump - [BUG] rb_sys_fail() - errno == 0

10 messages 2010/03/24

[#28954] [Feature #3010] slow require gems in ruby 1.9.1 — Miao Jiang <redmine@...>

Feature #3010: slow require gems in ruby 1.9.1

15 messages 2010/03/24

[#29179] [Bug #3071] Convert rubygems and rdoc to use psych — Aaron Patterson <redmine@...>

Bug #3071: Convert rubygems and rdoc to use psych

10 messages 2010/03/31

[ruby-core:28787] Re: [Feature #2065] An ancestors iterator

From: Yusuke ENDOH <mame@...>
Date: 2010-03-19 15:45:31 UTC
List: ruby-core #28787
Hi,

2010/3/20 Simon Chiang <redmine@ruby-lang.org>:
> So to clarify... ?How much any piece of code of a bottleneck depends on how frequently the code gets run, and that is application-specific. ?In my own application, it IS enough of a bottleneck for me to make this request because I run the code very frequently. ?In other applications, it may not be a bottleneck.
>
> For DSLs that want to have method-like inheritance, the lack of an ancestors iterator is a potential and unnecessary bottleneck. ?An each_ancestor iterator would, as per the benchmarks, significantly speed up a useful programming pattern that I think would be used more frequently if it were inherently faster. I hope that clarifies the purpose of this request.

I doubt if there is few real application whose bottleneck is
Module#ancestors.


> Using superclass would work in the example I gave you but not in general because as I understand it superclass does not visit modules. ?Using ancestors allows for method-like 'inheritance' because you can visit both modules and superclasses. Using superclass limits you to the class hierarchy.

Indeed.
I'd like to make up for my stupid suggestion by giving a patch :-)
I can commit this if matz approves.


diff --git a/class.c b/class.c
index fed2edf..51bc162 100644
--- a/class.c
+++ b/class.c
@@ -763,6 +763,42 @@ rb_mod_ancestors(VALUE mod)
     return ary;
 }

+/*
+ *  call-seq:
+ *     mod.each_ancestor -> nil
+ *
+ *  Yields each module included in <i>mod</i> (including <i>mod</i>
+ *  itself).
+ *
+ *     module Mod
+ *       include Math
+ *       include Comparable
+ *     end
+ *
+ *     Mod.each_ancestor {|c| p c }  #=> Mod, Comparable, Math
+ *     Math.each_ancestor {|c| p c } #=> Math
+ */
+
+VALUE
+rb_mod_each_ancestor(VALUE mod)
+{
+    VALUE p;
+
+    RETURN_ENUMERATOR(mod, 0, 0);
+
+    for (p = mod; p; p = RCLASS_SUPER(p)) {
+	if (FL_TEST(p, FL_SINGLETON))
+	    continue;
+	if (BUILTIN_TYPE(p) == T_ICLASS) {
+	    rb_yield(RBASIC(p)->klass);
+	}
+	else {
+	    rb_yield(p);
+	}
+    }
+    return Qnil;
+}
+
 #define VISI(x) ((x)&NOEX_MASK)
 #define VISI_CHECK(x,f) (VISI(x) == (f))

diff --git a/object.c b/object.c
index 0421824..6c8766e 100644
--- a/object.c
+++ b/object.c
@@ -2449,6 +2449,8 @@ rb_f_array(VALUE obj, VALUE arg)
     return rb_Array(arg);
 }

+extern VALUE rb_mod_each_ancestor(VALUE mod);
+
 /*
  *  Document-class: Class
  *
@@ -2657,6 +2659,7 @@ Init_Object(void)
     rb_define_method(rb_cModule, "include?", rb_mod_include_p, 1); /*
in class.c */
     rb_define_method(rb_cModule, "name", rb_mod_name, 0);  /* in variable.c */
     rb_define_method(rb_cModule, "ancestors", rb_mod_ancestors, 0);
/* in class.c */
+    rb_define_method(rb_cModule, "each_ancestor",
rb_mod_each_ancestor, 0); /* in class.c */

     rb_define_private_method(rb_cModule, "attr", rb_mod_attr, -1);
     rb_define_private_method(rb_cModule, "attr_reader",
rb_mod_attr_reader, -1);
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index f905431..4330d69 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -216,6 +216,15 @@ class TestModule < Test::Unit::TestCase

remove_rake_mixins(remove_json_mixins(remove_pp_mixins(String.ancestors))))
   end

+  def test_each_ancestor
+    a = []
+    User.each_ancestor {|m| a << m }
+    assert_equal([User, Mixin], a)
+    a = []
+    Mixin.each_ancestor {|m| a << m }
+    assert_equal([Mixin], a)
+  end
+
   CLASS_EVAL = 2
   @@class_eval = 'b'


-- 
Yusuke ENDOH <mame@tsg.ne.jp>

In This Thread