[#77789] [Ruby trunk Feature#12012] Add Boolean method — prodis@...
Issue #12012 has been updated by Fernando Hamasaki de Amorim.
4 messages
2016/10/27
[ruby-core:77754] [Ruby trunk Feature#12861] super in a block can be either lexically or dynamically scoped depending on how the block is invoked
From:
merch-redmine@...
Date:
2016-10-24 21:03:35 UTC
List:
ruby-core #77754
Issue #12861 has been updated by Jeremy Evans.
Tracker changed from Bug to Feature
Assignee set to Yukihiro Matsumoto
bug hit wrote:
> Jeremy Evans wrote:
> >
> > One could argue that super is currently always relative to the current, dynamic method
>
> Except it's not.
>
> ```ruby
> class Class1
> def self.foo
> 'Class1::foo'
> end
> end
>
> class Class2 < Class1
>
> def self.store_block(&block)
> @block = block
> end
>
> def self.foo
> store_block do
> super
> end
> end
>
> def self.call_stored_block
> @block.()
> end
>
> end
>
> Class2.foo
> Class2.call_stored_block # "Class1::foo"
> ```
>
> When the block with super is invoked by Class2.call_stored_block, foo is not the current dynamic method, it's not even on the stack, and yet super calls foo because it is lexically bound to it. That's the current typical behavior of super, i.e. lexical method binding. The one exception is when super is in a block/proc invoked as a method.
When the block with super is invoked by Class2.call_stored_block, `foo` is the current method at that point, according to `__method__`. This is simple to see by changing Class1.foo to raise an exception in your example, using `__method__` from inside the block:
~~~ ruby
class Class1
def self.foo(v)
raise v
end
end
class Class2 < Class1
def self.store_block(&block)
@block = block
end
def self.foo
store_block do
super(__method__.to_s)
end
end
def self.call_stored_block
@block.()
end
end
Class2.foo
Class2.call_stored_block
# super_test.rb:3:in `foo': foo (RuntimeError)
# from super_test.rb:15:in `block in foo'
# from super_test.rb:20:in `call_stored_block'
# from super_test.rb:26:in `<main>'
~~~
Notice how the backtrace states "block in foo" (in ruby 1.8.7, it just shows "foo"), and you can see that `__method__` in the block is :foo, show by the exception message.
It's already possible to get your desired behavior via super_method, changing ruby's behavior in regards to super will break a large amount of existing code, and the way super currently works in ruby makes sense (calling the super of the current `__method__`). This behavior dates back to at least ruby 1.8.7.
This is a request for a language behavior change, not a request for a bug fix. I'm changing this from Bug to Feature, and assigning to matz to make the decision.
----------------------------------------
Feature #12861: super in a block can be either lexically or dynamically scoped depending on how the block is invoked
https://bugs.ruby-lang.org/issues/12861#change-61057
* Author: bug hit
* Status: Open
* Priority: Normal
* Assignee: Yukihiro Matsumoto
----------------------------------------
```ruby
class Class1
def self.foo
'foo'
end
def self.method1
'method1'
end
end
class Class2 < Class1
def self.foo
bar do
super()
end
end
def self.bar(&block)
a = block.()
define_singleton_method :method1, &block
b = send(:method1)
c = block.()
[a, b, c]
end
end
p Class2.foo # ["foo", "method1", "foo"]
```
It doesn't seem like a good idea for a given language construct to be either lexically or dynamically scoped, depending on how its surrounding block is invoked (which is not visible at the point of definition). I think it would be better if super were always lexically scoped, and a different keyword (dynamic_super) were always dynamically scoped
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>