[#67346] Future of test suites for Ruby — Charles Oliver Nutter <headius@...>

I'll try to be brief so we can discuss all this. tl;dr: RubySpec is

19 messages 2015/01/05

[ruby-core:67266] [ruby-trunk - Bug #10684] Block arity changes through Enumerable methods

From: halostatue@...
Date: 2015-01-01 00:03:25 UTC
List: ruby-core #67266
Issue #10684 has been updated by Austin Ziegler.


It=E2=80=99s not that surprising to me.

While `Enumerable#detect` is written in C, in Ruby I might implement it as:

```ruby
module Enumerable
  def detect2
    return enum_for(:detect2) unless block_given?
    v =3D each { |x| break x if yield x }
    v =3D=3D self ? nil : v
  end
end
```

In this case, the C code is instructive:

```c
static VALUE
enum_find(int argc, VALUE *argv, VALUE obj)
{
    NODE *memo;
    VALUE if_none;

    rb_scan_args(argc, argv, "01", &if_none);
    RETURN_ENUMERATOR(obj, argc, argv);
    memo =3D NEW_MEMO(Qundef, 0, 0);
    rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
    if (memo->u3.cnt) {
	return memo->u1.value;
    }
    if (!NIL_P(if_none)) {
	return rb_funcall(if_none, id_call, 0, 0);
    }
    return Qnil;
}
```

In practice, it's doing it more like:

```ruby
module Enumerable
  def detect3
    return enum_for(:detect3) unless block_given?
    inject(nil) { |m, x|
      v =3D yield x
      m ||=3D v if v
      m
    }
  end
end
```

----------------------------------------
Bug #10684: Block arity changes through Enumerable methods
https://bugs.ruby-lang.org/issues/10684#change-50732

* Author: Jake Sower
* Status: Open
* Priority: Normal
* Assignee:=20
* Category:=20
* Target version:=20
* ruby -v: 2.2.0
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN
----------------------------------------
Blocks traveling through methods in Enumerable have their arity changed bef=
ore reaching #each.  Example:


class MyEnumerator
  include Enumerable

  def initialize(ary)
    @ary =3D ary
  end

  def each(&block)
    puts block.arity
    @ary.each(&block)
  end
end

my_enum =3D MyEnumerator.new([1,2,3])
my_enum.each{|x| x}    # outputs 1
my_enum.detect{|x| x}  # outputs -1



This is surprising behavior.  I would expect the output to be 1 in both cas=
es since the blocks appear identical to me as a programmer.



--=20
https://bugs.ruby-lang.org/

In This Thread

Prev Next