I’m learning Ruby and have found some interesting behaviour which I
cann’t understand myself yet.
Here’s some code and the output:
class Foo
def self.new(*args)
obj = super
yield
obj
end
end
Foo.new do
p self
end
Struct.new(“Foo”, :foo, :bar) do
p self
end
=> main
=> Struct::Foo
The first output is quite understandable because self is bounded to the
top-level class of the file and is sent to the closure.
But in the second line it seems that scope of self has been changed
somehow.
I’ve had a fast look on the source file struct.c and haven’t found
something special in the new method.
The same thing can also be found in the QtRuby bindings:
require ‘Qt4’
Qt::Application.new(ARGV) do
Qt::Widget.new do
self.window_title = 'Hello QtRuby v1.0'
resize(200, 100)
button = Qt::PushButton.new('Quit') do
connect(SIGNAL :clicked) { Qt::Application.instance.quit }
end
label = Qt::Label.new('<big>Hello Qt in the Ruby way!</big>')
self.layout = Qt::VBoxLayout.new do
add_widget(label, 0, Qt::AlignCenter)
add_widget(button, 0, Qt::AlignRight)
end
show
end
exec
end
Please, could anybody explain me how does this work. Links will do too.
Thanks for your response. I’ve almost grasped the idea.
Here’s an explanation is other words:
When you create a block you create a parcel that contains three things:
The code itself.
The “binding” (links to the surrounding variables).
The value of ‘self’ (this is how ruby knows which object to
invoke methods on).
When you normally ‘yield’ to a block, the block uses the value of ‘self’
saved in that parcel. On the other hand, when you do
‘somebody.eval_instance()’, the ‘self’ in that parcel is set to
‘somebody’.
It is common in GUI frameworks to use eval_instance() to make the code
look like DSL (google for “DSL”).
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.