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?
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’.
I remember wishing for this sort of thing in C, where I didn’t want to
clutter the ‘global namespace’ with my utility functions that were only
relevant within another function. Maybe that was poor design on my part.
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.
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?
They’re known as “local functions” I think (not sure if that is a universal
term for them). I use these from time to time in Pascal. I have several
uses for them:
To “tuck away” code in a function which makes the function hard to
follow. For example, if a “for” statement has 15 lines of code in it
(making code before and after the for statement spread apart), I might put
all that code up into a local function and the for statement will just call
it. The code itself isn’t particularly re-usable, so I leave it out of the
parent function’s namespace and keep it in a local function.
Same as #1, but especially when I call the same code from more than one
place in a function, and it’s, again, not particularly re-usable.
If the code ever hints at re-usability, then I find it a real home in a
namespace somewhere.
To override other functions temporarily (perhaps even permanently). This
is a bit like Aspect programming, I think. For example, if a function I’ve
written calls printf, but for a test I want all the data being printed to go
to both a file for logging purposes and to a TCP/IP connection for remote
logging, I could write a local function called printf. Being able to
re-define a function on-the-fly for quick debugging purposes is very nice.
I like the fact that Ruby has local functions. It’s mainly a procedural
programming device, but personally, while I love Ruby’s pure-OOP-ness, I
think it’s wise to also incorporate other programming idioms.
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
···
On Thursday, 17 July 2003 at 23:57:24 +0900, Michael Campbell wrote:
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’.
–
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
I can only remember ever seeing this in Pascal (not that I have a wide language experience base).
Modula 2 had a feature called modules, which you could define within other modules and so on. The language design did not implicitly stop you doing this and being true to the design in a zen like maschocistic kind of way Wirth let the language out of the
door with this ‘feature’. No one ever found a real use for it and compiler writers hated it.
One of Modula 3s strong points was that you couldn’t nest modules. But the ruling was arbitary.
Matz seems to be going with Wirth on this one rather than impose an arbitary constraint. Like the fact that you can actually type in x++ and --x without a special ‘lint’ rule to catch them (they just dont behave as expected, part of the problem C types
have with it).
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.
···
On Fri, Jul 18, 2003 at 02:17:42AM +0900, Phil Tomson wrote:
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.
They’re known as “local functions” I think (not sure if that is a
universal
term for them). I use these from time to time in Pascal. I have several
uses for them:
To “tuck away” code in a function which makes the function hard to
follow. For example, if a “for” statement has 15 lines of code in it
(making code before and after the for statement spread apart), I might put
all that code up into a local function and the for statement will just
call
it. The code itself isn’t particularly re-usable, so I leave it out of
the
parent function’s namespace and keep it in a local function.
Same as #1, but especially when I call the same code from more than one
place in a function, and it’s, again, not particularly re-usable.
If the code ever hints at re-usability, then I find it a real home in a
namespace somewhere.
To override other functions temporarily (perhaps even permanently).
This
is a bit like Aspect programming, I think. For example, if a function
I’ve
written calls printf, but for a test I want all the data being printed to
go
to both a file for logging purposes and to a TCP/IP connection for remote
logging, I could write a local function called printf. Being able to
re-define a function on-the-fly for quick debugging purposes is very nice.
I like the fact that Ruby has local functions. It’s mainly a procedural
programming device, but personally, while I love Ruby’s pure-OOP-ness, I
think it’s wise to also incorporate other programming idioms.
But I think we’ve seen that these aren’t really
local functions… isn’t that true? If I do
They’re known as “local functions” I think (not sure if that is a universal
term for them). I use these from time to time in Pascal. I have several
uses for them:
I’m confused: Are they supposed to be local? (Ruby-1.8.0-pre3)
~$ irb
def fred()
puts “Fred here!”
def bob()
puts “Bob here!”
end
bob()
end
=> nil
bob()
NoMethodError: undefined method `bob’ for main:Object
from (irb):8
fred()
Fred here!
Bob here!
=> nil
bob()
Bob here!
=> nil
It looks like it’s just an unexpected (for me) side-effect of method
definitions being done at runtime.
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:0x2b91d50>
irb(main):009:0> c.x
NoMethodError: undefined method `x’ for #<C:0x2b91d50>
from (irb):9
irb(main):010:0> c.fred
=> nil
irb(main):011:0> c.x
x
=> nil
This means you could do something, er, interesting, like this:
irb(main):001:0> class C
irb(main):002:1> def initialize
irb(main):003:2> def m
irb(main):004:3> puts “m”
irb(main):005:3> end
irb(main):006:2> end
irb(main):007:1> end
=> nil
irb(main):008:0> C.instance_methods
=>
irb(main):009:0> c = C.new
=> #<C:0x2b8d610>
irb(main):010:0> c.m
m
=> nil
Why would you want to do that? I’m not exactly sure…
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
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
This seems unintuitive to me. I would expect variables declared in a
parent method to be accessible in child methods. Can someone tell me why
I’m wrong? I’m sure I am.
Chad
···
On Fri, 18 Jul 2003, Brian Candler wrote:
On Fri, Jul 18, 2003 at 02:17:42AM +0900, Phil Tomson wrote:
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();
}
Hmm, I think ‘x’ has the same visibility as ‘fred’.
True, but it doesn’t exist until fred is called:
This means you could do something, er, interesting, like this:
Why would you want to do that? I’m not exactly sure…
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();
}
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
This seems unintuitive to me. I would expect variables declared in a
parent method to be accessible in child methods. Can someone tell me why
I’m wrong? I’m sure I am.
Imagine the local function “my_meth” is defined outside of “go.” The
variable “num” wouldn’t be accessible there, either. I think “my_meth” is
thought of as a proc which just happens to be defined within “go” and not
really local to “go.” So, “my_meth” is not truly a local function then, I
think.
Sean O'Dell
···
On Fri, 18 Jul 2003, Brian Candler wrote:
On Fri, Jul 18, 2003 at 02:17:42AM +0900, Phil Tomson wrote:
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.
···
On Fri, Jul 18, 2003 at 03:00:13AM +0900, Chad Fowler wrote:
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