Forum: Ruby-core [ruby-trunk - Bug #7872][Open] `block_given?` does not work inside `define_method`

Posted by alexeymuranov (Alexey Muranov) (Guest)
on 2013-02-17 02:55
(Received via mailing list)
Issue #7872 has been reported by alexeymuranov (Alexey Muranov).

----------------------------------------
Bug #7872: `block_given?` does not work inside `define_method`
https://bugs.ruby-lang.org/issues/7872

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version:
ruby -v: 2.0.0-rc2


=begin
Is this the expected behavior?

 define_method :try do
   block_given? ? yield : 'no block'
 end

 try { 'block' } # => "no block"

However:

 def try_again
   block_given? ? yield : 'no block'
 end

 try_again { 'block' } # => "block"

=end
Posted by drbrain (Eric Hodel) (Guest)
on 2013-02-17 05:16
(Received via mailing list)
Issue #7872 has been updated by drbrain (Eric Hodel).

Tracker changed from Bug to Feature
Target version set to next minor

=begin
The behavior in 1.9:

  $ ruby19 -ve 'class C; define_method :x do p block_given? end; end; 
C.new.x { }'
  ruby 1.9.3p374 (2013-01-15 revision 38858) [x86_64-darwin12.2.1]
  false

Is the same as in 2.0:

  $ ruby20 -ve 'class C; define_method :x do p block_given? end; end; 
C.new.x { }'
  ruby 2.0.0dev (2013-02-08 trunk 39138) [x86_64-darwin12.2.1]
  false

So I have switched it to a feature request.
=end

----------------------------------------
Feature #7872: `block_given?` does not work inside `define_method`
https://bugs.ruby-lang.org/issues/7872#change-36354

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: next minor


=begin
Is this the expected behavior?

 define_method :try do
   block_given? ? yield : 'no block'
 end

 try { 'block' } # => "no block"

However:

 def try_again
   block_given? ? yield : 'no block'
 end

 try_again { 'block' } # => "block"

=end
Posted by alexeymuranov (Alexey Muranov) (Guest)
on 2013-02-17 13:28
(Received via mailing list)
Issue #7872 has been updated by alexeymuranov (Alexey Muranov).


Ok.  Is it actually possible to somehow force `def ... end` for instance 
methods behave identically with `define_method` method in the block 
form?
----------------------------------------
Feature #7872: `block_given?` does not work inside `define_method`
https://bugs.ruby-lang.org/issues/7872#change-36435

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: next minor


=begin
Is this the expected behavior?

 define_method :try do
   block_given? ? yield : 'no block'
 end

 try { 'block' } # => "no block"

However:

 def try_again
   block_given? ? yield : 'no block'
 end

 try_again { 'block' } # => "block"

=end
Posted by ko1 (Koichi Sasada) (Guest)
on 2013-02-18 01:34
(Received via mailing list)
Issue #7872 has been updated by ko1 (Koichi Sasada).

Assignee set to matz (Yukihiro Matsumoto)

(a) def...end and (b) define_method(...){...} is completely different.

(1) On (b), outer scope

  a = 1
  define_method(:foo) do
    p a # access to outer scope
  end

(2) (1) means that the passed block is outer block

  class C; end
  def def_method mid
    C.module_eval{
      define_method(mid) do
        p block_given?
        yield if block_given?
      end
    }
  end

  def_method(:foo)
  obj = C.new
  obj.foo
  obj.foo{p 1}

  def_method(:bar){p :def_foo}
  obj.bar
  obj.bar{p 2}

#=>

  false
  false
  true
  :def_foo
  true
  :def_foo

(3) You can pass block using block parameter

  define_method(:foo){|&b|
    p [b, block_given?]
  }
  foo   #=> [nil, false]
  foo{} #=> [#<Proc:0x22d08f0@t.rb:5>, false]


----------------------------------------
Feature #7872: `block_given?` does not work inside `define_method`
https://bugs.ruby-lang.org/issues/7872#change-36474

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: next minor


=begin
Is this the expected behavior?

 define_method :try do
   block_given? ? yield : 'no block'
 end

 try { 'block' } # => "no block"

However:

 def try_again
   block_given? ? yield : 'no block'
 end

 try_again { 'block' } # => "block"

=end
Posted by alexeymuranov (Alexey Muranov) (Guest)
on 2013-02-18 10:43
(Received via mailing list)
Issue #7872 has been updated by alexeymuranov (Alexey Muranov).


@ko1 thanks for the explanations, i will think about them.
----------------------------------------
Feature #7872: `block_given?` does not work inside `define_method`
https://bugs.ruby-lang.org/issues/7872#change-36496

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: next minor


=begin
Is this the expected behavior?

 define_method :try do
   block_given? ? yield : 'no block'
 end

 try { 'block' } # => "no block"

However:

 def try_again
   block_given? ? yield : 'no block'
 end

 try_again { 'block' } # => "block"

=end
Posted by rkh (Konstantin Haase) (Guest)
on 2013-04-12 17:44
(Received via mailing list)
Issue #7872 has been updated by rkh (Konstantin Haase).


Rebinding block_given? on define_method might be confusing, as the block 
might be passed to an API without the user being aware of it being used 
with define_method.
----------------------------------------
Feature #7872: `block_given?` does not work inside `define_method`
https://bugs.ruby-lang.org/issues/7872#change-38495

Author: alexeymuranov (Alexey Muranov)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: next minor


=begin
Is this the expected behavior?

 define_method :try do
   block_given? ? yield : 'no block'
 end

 try { 'block' } # => "no block"

However:

 def try_again
   block_given? ? yield : 'no block'
 end

 try_again { 'block' } # => "block"

=end
Posted by marcandre (Marc-Andre Lafortune) (Guest)
on 2013-04-12 21:14
(Received via mailing list)
Issue #7872 has been updated by marcandre (Marc-Andre Lafortune).

Status changed from Open to Rejected

I'll mark this request as rejected, as it appears based on the 
misconception that `block_given?` was `false` while `yield` would 
actually succeed; both refer correctly to the outerscope's presence of 
the block and arguments, including the block, must be declared 
explicitly as Koichi points out.

Moreover the request is woefully incomplete as it stands.
If someone feels like there is a feature to be requested, a sensible and 
more complete proposal must be made, in particular saying if all of 
`block_given?`, `yield`, `Proc.new`, eval(...), etc..., should refer to 
the inner scope and why, how this would affect `define_method(:foo, 
&block)` (where block is defined somewhere else; would `block_given?` & 
al. be magically rebound?), would it apply to `define_singleton_method`, 
etc..., why that would be a good thing and what kind of 
incompatibilities we should expect.
----------------------------------------
Feature #7872: `block_given?` does not work inside `define_method`
https://bugs.ruby-lang.org/issues/7872#change-38506

Author: alexeymuranov (Alexey Muranov)
Status: Rejected
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: next minor


=begin
Is this the expected behavior?

 define_method :try do
   block_given? ? yield : 'no block'
 end

 try { 'block' } # => "no block"

However:

 def try_again
   block_given? ? yield : 'no block'
 end

 try_again { 'block' } # => "block"

=end
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.