0x1f – There are no nested functions in ruby!

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.

Advertisements

3 responses to “0x1f – There are no nested functions in ruby!

  1. 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.

  2. 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?

  3. 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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s