Long time no read, I know. Well, I have been away.
Anyways, while I am not back yet, I stumbled across something that made me wonder: consider this:
class X
def self.a
def self.b; "b"; end
b()
end
def self.x
b
end
end
The ruby feature which allows you to define a function within another function is relatively new to me. Since I found out about it I used it to split a function into several parts but not to publish the parts in any namespace accessible from the outside, i.e. the parts should be accessible only from within the method.
Turns out that I was wrong. Apparently a “not-really inner function” is defined at whatever outer level exists (hence the need for the “self” part in “def self.b; …; end” in the example above). The method “b” is defined on the X class object, i.e. as if was written
class X
def self.b; "b"; end
def self.a; b(); end
end
Seems I will stop using that idiom.
Filed under: Uncategorized | 3 Comments
The entry is a bit confusing to me. There simply are no nested functions in ruby.
the first snippet is just reopening self to add another method to it. It’s the same idiom as this:
a = “foo”
def a.bar; puts “hello”; end
You can achieve the effect of helper functions by using procs or lambdas:
def foo
square = lambda { |x| x*x }
return square[3] + square[5]
end
But it would probably cleaner to use helper classes or private methods.
Hi Bob, thanks for your comment. With my background (coming from C,C++ and a number of similar languages) I assumed that when you are able to def a symbol within a codeblock the resulting symbol is not visible outside that codeblock. And I was wrong. But to not confuse anyone I will change the post’s title.
Regarding your code snippet: I still do not see where this is the same as mine; mine tried to define a method locally within another method, which does not work. Similar examples include:
class Y
def a
def b; “b”; end
b()
end
end
and please note that “def self.b” wouldn’t work here. But as neither doesn’t achieve anything good I will stick to helper modules in the future. Not lambdas though: I suspect the ruby interpreter of still not being able to cache a lambda away efficiently,
Speaking of syntax surprises: lambdas do take bracket parentheses as well?
re Brackets: that’s just a ahorthand for `call`
re Snippets: I just wanted to demonstrate that the “def object.methodname” syntax in ruby can be used anywhere and on anything, not just inside method definitions.
I meant to say is that `def self.b; “b”; end` is not special inside method definitions, and that the effect it has just follows naturally from what self is bound to inside the method definition.