What's the point?

J

Jim Freeze

Hi

I've known for some time that methods can be defined inside
methods, but I am still wondering what's the point.

def fred
def x
puts "x"
end
x
end

fred
x

produces
x
x

Why would any sane person do such a thing? :)
 
Y

Yukihiro Matsumoto

Hi,

In message "What's the point?"

|I've known for some time that methods can be defined inside
|methods, but I am still wondering what's the point.

It's for orthogonality's sake. Don't do it.

matz.
 
R

Robert Klemme

It's for orthogonality's sake. Don't do it.

Matz has this great gift of being concise and to the point. I hope that
one day I'll arrive there, too...

robert
 
J

Jim Freeze

I can only remember ever seeing this in Pascal (not that I have a wide
language experience base).

I can imagine the use for such a construct is similar to "private" methods
in a class (in a Java context). You want abstract some procedure or
algorithm, but limit its visibility. In the above case, 'x' is only known
to 'fred'. If fred was doing a lot of repetitious stuff that wasn't
relevant outside fred, it might make sense to abstract the
repetitious/common stuff into 'x'.

Hmm, I think 'x' has the same visibility as 'fred'.

irb
irb(main):001:0> class C
irb(main):002:1> def fred
irb(main):003:2> def x
irb(main):004:3> puts "x"
irb(main):005:3> end
irb(main):006:2> end
irb(main):007:1> end
=> nil
irb(main):008:0> c=C.new
=> #<C:0x183148>
irb(main):009:0> c.fred
=> nil
irb(main):010:0> c.x
x


--
Jim Freeze
----------
Aphorism, n.:
A concise, clever statement.
Afterism, n.:
A concise, clever statement you don't think of until too late.
-- James Alexander Thom
 
P

Phil Tomson

Hi

I've known for some time that methods can be defined inside
methods, but I am still wondering what's the point.

def fred
def x
puts "x"
end
x
end

Used to be you couldn't do that; apparently, it's new in 1.8.

As to your other question about "why?" - Sometimes I used to do this in
Perl to localize some functionality within a method (..errr, function or
subroutine in Perl parlance). Usually this was in a sort of refactoring
stage where I'd look at my sub and find that I had some duplicated code in
it that I could collect into another sub-sub.

BTW: It seems that whenever I look at Python code (which isn't too often)
I see this being done. So I guess when something is possible it will get
used.

Phil
 
B

Brian Candler

As to your other question about "why?" - Sometimes I used to do this in
Perl to localize some functionality within a method (..errr, function or
subroutine in Perl parlance). Usually this was in a sort of refactoring
stage where I'd look at my sub and find that I had some duplicated code in
it that I could collect into another sub-sub.

Beware, thar be demons.

sub foo {
my $x = $_[0];
sub bar {
print "x is $x\n";
}
bar();
}

foo("one");
foo("two");

Prints:
x is one
x is one

To be fair, if you run perl with -w, you get a cryptic warning:
Variable "$x" will not stay shared at x.pl line 4.

Regards,

Brian.
 
B

Brian Candler

In Ruby, the equivalent code seems to fail, with local variables not being
accessible in nested methods. For example:

irb(main):018:0> def go
irb(main):019:1> 1.upto(10) do |num|
irb(main):020:2* def my_meth
irb(main):021:3> puts "Printing #{num}"
irb(main):022:3> end
irb(main):023:2> end
irb(main):024:1> end
nil
irb(main):025:0> go
1
irb(main):026:0> my_meth
NameError: undefined local variable or method `num' for
#<Object:0x2b992c8>
from (irb):21:in `my_meth'
from (irb):26
from ?:0

Yep, 'def' always starts a new scope, and no local variables are available
outside:

x = 1
def hello
puts x
end
hello # NameError: undefined local variable or method `x'

I don't think there's any *fundamental* reason why it couldn't happen,
because you can get the effect if you try hard enough:

x = 1
p = proc { puts x }
class <<self; self; end.instance_eval { define_method:)hello, p) }
hello #>> 1
x = 4
hello #>> 4

However it would make the scoping rules pretty nasty. Suppose I defined a
local variable using 'x=1' outside of a method, e.g.

class Foo
x = 1
def bar
...
obj.each do |x| # << binds to the same 'x'!!
...
end
end
end

Every single method I defined from that point onwards which referred to 'x'
would bind to the *same* x instead of having its own local 'x'. Even
multiple instances of the class would share the same variable! x would
become like @@x.

At least when 'def' starts a fresh scope, then you don't have to worry about
your local variables being polluted from outside.

Also, the method/local variable ambiguity would become a problem: it would
be impossible to invoke a method called 'x' in the above example either,
because you would be referring to the local variable instead.

Cheers,

Brian.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top