There are three ways to create a new scope in ruby.
Classes, Modules, and Methods.
Your class creates a scope, and each of your methods create a scope that contain bindings specific to them. Closures are special though. A closure will grab the bindings that are around when you define the block and the block specific bindings disappear after the block ends. For example:
def my_method
#Method scope
x = "Goodbye"
yield("Cruel")
end
x = "Hello"
#Closure says "I am going to grab the local bindings from my scope
my_method {|y| "#{x}, #{y} world" }
When ever you write the code
obj.define_singleton_method(:say1) { msg }
The only local bindings the closure grabs is 'obj'
This can be demonstrated by modifying the code like so:
def d2(obj)
puts "in the scope of method :d2, I have acces to the :msg method: #{methods.include?(:msg)}"
puts "---"
obj.define_singleton_method(:say2) do
puts "in the scope of this closure, I have acces to the :msg method: #{methods.include?(:msg)}"
puts "Things I do have access to: "
puts methods
puts local_variables
end
end
A simple print statement of the most important part of ruby, self, will show you that you are operating in different scopes. Check out the code below:
def d2(obj)
puts "in the scope of method :d2, I am operating as #{self}"
puts "---"
obj.define_singleton_method(:say2) do
puts "in the scope of this closure, I am operating as #{self}"
end
end
So in short, the reason is because of scope. Whenever you declare bound = msg you are making the contents of msg local to the method and then the closure then can pick up the local binding value of msg.
If you want to read more about how this works, I highly recommend "The Pragmatic Programmers - Metaprogramming Ruby" You will learn a lot about self, and closures.
http://www.amazon.com/Metaprogramming-Ruby-Program-Like-Facets/dp/1941222129
----EDIT----
"Why is"
def p
Proc.new { msg }
end
different than
def d2(obj)
obj.define_singleton_method(:say2) { msg }
end
It is different because self inside the block is different. Inside the method definition "p", the block has access to instance variables and methods, whereas the method "d2" has a block that only has access to Object. We can prove this with a little monkeypatching. Add this code:
In ruby everything is object (or almost). For example:
String.class # Class
The class of String is Class, so String is an instance of Class.
The ruby model object is not easy to understand at the first sight when you come from C++ or Java.
When you do:
class String
def abc
"hey"
end
end
puts "foo".abc #hey
You're reopening the class String and define a new instance method abc. You can also add a new method to the String class thanks to the keyword self, like this:
class String
def self.abc
"hey from class :)"
end
end
puts String.abc #hey from class :)
Here, you're adding a abc method to the String object itself.
If you're interested to learn how ruby works in depth, there is a lot of book, one of my favorite is this one:https://www.amazon.co.uk/Metaprogramming-Ruby-Program-Like-Facets/dp/1941222129
as Tiago said, the class reopening method is called Monkey patching and you have to use it sparingly :)
Previous answer:
You can use the self keyword, like this:
class String
def self.abc
"hey from class :)"
end
end
puts String.abc #hey from class :)
The answer has to do with
self
and scopesThere are three ways to create a new scope in ruby. Classes, Modules, and Methods.
Your class creates a scope, and each of your methods create a scope that contain bindings specific to them. Closures are special though. A closure will grab the bindings that are around when you define the block and the block specific bindings disappear after the block ends. For example:
When ever you write the code
The only local bindings the closure grabs is 'obj' This can be demonstrated by modifying the code like so:
A simple print statement of the most important part of ruby, self, will show you that you are operating in different scopes. Check out the code below:
So in short, the reason is because of scope. Whenever you declare
bound = msg
you are making the contents ofmsg
local to the method and then the closure then can pick up the local binding value ofmsg
.If you want to read more about how this works, I highly recommend "The Pragmatic Programmers - Metaprogramming Ruby" You will learn a lot about self, and closures. http://www.amazon.com/Metaprogramming-Ruby-Program-Like-Facets/dp/1941222129
----EDIT---- "Why is"
def p Proc.new { msg } end
different than
def d2(obj) obj.define_singleton_method(:say2) { msg } end
It is different because self inside the block is different. Inside the method definition "p", the block has access to instance variables and methods, whereas the method "d2" has a block that only has access to Object. We can prove this with a little monkeypatching. Add this code:
class Object def msg "GoodBye" end
New answer:
So you're asking how this is possible.
In ruby everything is object (or almost). For example:
The class of
String
isClass
, soString
is an instance ofClass
.The ruby model object is not easy to understand at the first sight when you come from
C++
orJava
.When you do:
You're reopening the class
String
and define a new instance methodabc
. You can also add a new method to theString
class thanks to the keywordself
, like this:Here, you're adding a
abc
method to theString
object itself.If you're interested to learn how ruby works in depth, there is a lot of book, one of my favorite is this one:https://www.amazon.co.uk/Metaprogramming-Ruby-Program-Like-Facets/dp/1941222129
as Tiago said, the class reopening method is called Monkey patching and you have to use it sparingly :)
Previous answer:
You can use the
self
keyword, like this:I haven't had a chance to look through it in-depth yet, but this looks pretty interesting: https://github.com/donnemartin/system-design-primer
As far as things that have had an important impact in my learning path, I do have a few Ruby books I really like (the key here is to get your hands dirty with code as you read along): - https://www.amazon.com/Ruby-Under-Microscope-Illustrated-Int... - https://www.amazon.com/Metaprogramming-Ruby-Program-Like-Fac... - https://gumroad.com/l/rebuilding_rails
I think reading about (and looking at the code) for things you use and trying to understand how they work under the hood has been super useful: http://aosabook.org/en/index.html
Having smart people around to learn from is extremely helpful too.
Happy to chat more if you'd like. Just drop me a line: connor[at]opendoor[dot]com