mirror of https://github.com/KLayout/klayout.git
Ruby iterators now automatically return an Enumerator if no block is given - allows very cool code ..
This commit is contained in:
parent
a5d675304c
commit
4c127b4644
|
|
@ -499,6 +499,16 @@ public:
|
||||||
a = A::new
|
a = A::new
|
||||||
a.each { |i| ... }</pre>
|
a.each { |i| ... }</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If no block is given, an Enumerator object is created. Enumerators
|
||||||
|
are a Ruby feature. Enumerators support many convenient methods
|
||||||
|
like sort, inject, collect, select etc. Here is an example:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
# turns all elements returned by the iterator into strings and sorts them
|
||||||
|
sorted = a.each.collect(&:to_s).sort</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Iterators match very well between C++ and Ruby so there are no real issues here.
|
Iterators match very well between C++ and Ruby so there are no real issues here.
|
||||||
The return type of the iterators is mapped to Ruby's block arguments using the
|
The return type of the iterators is mapped to Ruby's block arguments using the
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,8 @@ public:
|
||||||
{
|
{
|
||||||
std::vector<tl::BacktraceElement> bt;
|
std::vector<tl::BacktraceElement> bt;
|
||||||
bt.push_back (tl::BacktraceElement (rb_sourcefile (), rb_sourceline ()));
|
bt.push_back (tl::BacktraceElement (rb_sourcefile (), rb_sourceline ()));
|
||||||
rba_get_backtrace_from_array (rb_funcall (rb_mKernel, rb_intern ("caller"), 0), bt, 0);
|
static ID id_caller = rb_intern ("caller");
|
||||||
|
rba_get_backtrace_from_array (rb_funcall (rb_mKernel, id_caller, 0), bt, 0);
|
||||||
return bt;
|
return bt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,7 +114,8 @@ public:
|
||||||
// But the purpose is a relative compare, so efficiency is not sacrificed here
|
// But the purpose is a relative compare, so efficiency is not sacrificed here
|
||||||
// for unnecessary consistency.
|
// for unnecessary consistency.
|
||||||
int d = 1;
|
int d = 1;
|
||||||
VALUE backtrace = rb_funcall (rb_mKernel, rb_intern ("caller"), 0);
|
static ID id_caller = rb_intern ("caller");
|
||||||
|
VALUE backtrace = rb_funcall (rb_mKernel, id_caller, 0);
|
||||||
if (TYPE (backtrace) == T_ARRAY) {
|
if (TYPE (backtrace) == T_ARRAY) {
|
||||||
d += RARRAY_LEN(backtrace);
|
d += RARRAY_LEN(backtrace);
|
||||||
}
|
}
|
||||||
|
|
@ -933,16 +935,18 @@ method_adaptor (int mid, int argc, VALUE *argv, VALUE self, bool ctor)
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
|
|
||||||
|
static ID id_set = rb_intern ("set");
|
||||||
|
|
||||||
VALUE signal_handler = p->signal_handler (meth);
|
VALUE signal_handler = p->signal_handler (meth);
|
||||||
|
|
||||||
if (rb_block_given_p ()) {
|
if (rb_block_given_p ()) {
|
||||||
|
|
||||||
VALUE proc = rb_block_proc ();
|
VALUE proc = rb_block_proc ();
|
||||||
RB_GC_GUARD (proc);
|
RB_GC_GUARD (proc);
|
||||||
ret = rba_funcall2_checked (signal_handler, rb_intern ("set"), 1, &proc);
|
ret = rba_funcall2_checked (signal_handler, id_set, 1, &proc);
|
||||||
|
|
||||||
} else if (argc > 0) {
|
} else if (argc > 0) {
|
||||||
ret = rba_funcall2_checked (signal_handler, rb_intern ("set"), argc, argv);
|
ret = rba_funcall2_checked (signal_handler, id_set, argc, argv);
|
||||||
} else {
|
} else {
|
||||||
ret = signal_handler;
|
ret = signal_handler;
|
||||||
}
|
}
|
||||||
|
|
@ -991,6 +995,24 @@ method_adaptor (int mid, int argc, VALUE *argv, VALUE self, bool ctor)
|
||||||
p->set (obj, true, false, true, self);
|
p->set (obj, true, false, true, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (meth->ret_type ().is_iter () && ! rb_block_given_p ()) {
|
||||||
|
|
||||||
|
// calling an iterator method without block -> deliver an enumerator using "to_enum"
|
||||||
|
|
||||||
|
static ID id_to_enum = rb_intern ("to_enum");
|
||||||
|
|
||||||
|
VALUE method_sym = ID2SYM (rb_intern (meth->primary_name ().c_str ()));
|
||||||
|
|
||||||
|
if (argc == 0) {
|
||||||
|
ret = rba_funcall2_checked (self, id_to_enum, 1, &method_sym);
|
||||||
|
} else {
|
||||||
|
std::vector<VALUE> new_args;
|
||||||
|
new_args.reserve (size_t (argc + 1));
|
||||||
|
new_args.push_back (method_sym);
|
||||||
|
new_args.insert (new_args.end (), argv, argv + argc);
|
||||||
|
ret = rba_funcall2_checked (self, id_to_enum, argc + 1, new_args.begin ().operator-> ());
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
void *obj = 0;
|
void *obj = 0;
|
||||||
|
|
|
||||||
|
|
@ -733,6 +733,8 @@ class Basic_TestClass < TestBase
|
||||||
arr = []
|
arr = []
|
||||||
b.each_b_copy { |bb| arr.push(bb.b2) }
|
b.each_b_copy { |bb| arr.push(bb.b2) }
|
||||||
assert_equal(arr, ["a", "y", "uu"])
|
assert_equal(arr, ["a", "y", "uu"])
|
||||||
|
# through enumerator
|
||||||
|
assert_equal(b.each_b_copy.collect(&:b2), ["a", "y", "uu"])
|
||||||
|
|
||||||
arr = []
|
arr = []
|
||||||
b.each_b_copy { |bb| bb.b5(bb.b2 + "x"); arr.push(bb.b2) }
|
b.each_b_copy { |bb| bb.b5(bb.b2 + "x"); arr.push(bb.b2) }
|
||||||
|
|
@ -745,6 +747,8 @@ class Basic_TestClass < TestBase
|
||||||
arr = []
|
arr = []
|
||||||
b.each_b_cref { |bb| arr.push(bb.b2) }
|
b.each_b_cref { |bb| arr.push(bb.b2) }
|
||||||
assert_equal(arr, ["a", "y", "uu"])
|
assert_equal(arr, ["a", "y", "uu"])
|
||||||
|
# through enumerator
|
||||||
|
assert_equal(b.each_b_cref.collect(&:b2), ["a", "y", "uu"])
|
||||||
|
|
||||||
arr = []
|
arr = []
|
||||||
# this works, since the "const B &" will be converted to a copy
|
# this works, since the "const B &" will be converted to a copy
|
||||||
|
|
@ -759,6 +763,8 @@ class Basic_TestClass < TestBase
|
||||||
arr = []
|
arr = []
|
||||||
b.each_b_cptr { |bb| arr.push(bb.b2) }
|
b.each_b_cptr { |bb| arr.push(bb.b2) }
|
||||||
assert_equal(arr, ["a", "y", "uu"])
|
assert_equal(arr, ["a", "y", "uu"])
|
||||||
|
# through enumerator
|
||||||
|
assert_equal(b.each_b_cptr.collect(&:b2), ["a", "y", "uu"])
|
||||||
|
|
||||||
arr = []
|
arr = []
|
||||||
# const references cannot be modified
|
# const references cannot be modified
|
||||||
|
|
@ -778,6 +784,8 @@ class Basic_TestClass < TestBase
|
||||||
arr = []
|
arr = []
|
||||||
b.each_b_ref { |bb| arr.push(bb.b2) }
|
b.each_b_ref { |bb| arr.push(bb.b2) }
|
||||||
assert_equal(arr, ["a", "y", "uu"])
|
assert_equal(arr, ["a", "y", "uu"])
|
||||||
|
# through enumerator
|
||||||
|
assert_equal(b.each_b_ref.collect(&:b2), ["a", "y", "uu"])
|
||||||
|
|
||||||
arr = []
|
arr = []
|
||||||
b.each_b_ref { |bb| bb.b5(bb.b2 + "x"); arr.push(bb.b2) }
|
b.each_b_ref { |bb| bb.b5(bb.b2 + "x"); arr.push(bb.b2) }
|
||||||
|
|
@ -790,6 +798,8 @@ class Basic_TestClass < TestBase
|
||||||
arr = []
|
arr = []
|
||||||
b.each_b_ptr { |bb| arr.push(bb.b2) }
|
b.each_b_ptr { |bb| arr.push(bb.b2) }
|
||||||
assert_equal(arr, ["ax", "yx", "uux"])
|
assert_equal(arr, ["ax", "yx", "uux"])
|
||||||
|
# through enumerator
|
||||||
|
assert_equal(b.each_b_ptr.collect(&:b2), ["ax", "yx", "uux"])
|
||||||
|
|
||||||
arr = []
|
arr = []
|
||||||
b.each_b_ptr { |bb| bb.b5(bb.b2 + "x"); arr.push(bb.b2) }
|
b.each_b_ptr { |bb| bb.b5(bb.b2 + "x"); arr.push(bb.b2) }
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,8 @@ class DBPolygon_TestClass < TestBase
|
||||||
arr = []
|
arr = []
|
||||||
a.each_point_hull { |p| arr.push( p.to_s ) }
|
a.each_point_hull { |p| arr.push( p.to_s ) }
|
||||||
assert_equal( arr, ["5,-10", "5,15", "20,15", "20,-10"] )
|
assert_equal( arr, ["5,-10", "5,15", "20,15", "20,-10"] )
|
||||||
|
# with enumerator
|
||||||
|
assert_equal( a.each_point_hull.collect(&:to_s), ["5,-10", "5,15", "20,15", "20,-10"] )
|
||||||
|
|
||||||
b = a.dup
|
b = a.dup
|
||||||
|
|
||||||
|
|
@ -130,6 +132,8 @@ class DBPolygon_TestClass < TestBase
|
||||||
arr = []
|
arr = []
|
||||||
a.each_point_hole(0) { |p| arr.push( p.to_s ) }
|
a.each_point_hole(0) { |p| arr.push( p.to_s ) }
|
||||||
assert_equal( arr, ["1,2", "2,2", "2,6"] )
|
assert_equal( arr, ["1,2", "2,2", "2,6"] )
|
||||||
|
# with enumerator
|
||||||
|
assert_equal( a.each_point_hole(0).collect(&:to_s), ["1,2", "2,2", "2,6"] )
|
||||||
|
|
||||||
arr = []
|
arr = []
|
||||||
a.each_edge { |p| arr.push( p.to_s ) }
|
a.each_edge { |p| arr.push( p.to_s ) }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue