What's the point?

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? :slight_smile:

···


Jim Freeze

The truth is what is; what should be is a dirty lie.
– Lenny Bruce

FYI, they can’t in 1.6.8:

$ cat x.rb
def fred
def x
puts “x”
end
x
end
$ ruby x.rb
x.rb:2: nested method definition

···

On Thu, Jul 17, 2003 at 11:30:08PM +0900, Jim Freeze wrote:

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

Hi,

···

In message “What’s the point?” on 03/07/17, Jim Freeze jim@freeze.org writes:

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.

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? :slight_smile:

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.

In article 20030717103702.A3418@freeze.org,

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

···

Jim Freeze jim@freeze.org wrote:

“Jim Freeze” jim@freeze.org wrote in message
news:20030717103702.A3418@freeze.org

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? :slight_smile:

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:

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

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

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

Sean O'Dell

“Yukihiro Matsumoto” matz@ruby-lang.org schrieb im Newsbeitrag
news:1058453207.121971.1366.nullmailer@picachu.netlab.jp…

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

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

Michael Campbell wrote:

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

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.

···

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:

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

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

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

def alpha
def beta
#…
end
#…
end

Then isn’t beta callable from outside alpha?

Hal

···

----- Original Message -----
From: “Sean O’Dell” sean@REMOVEME.celsoft.com.web-hosting.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, July 17, 2003 12:37 PM
Subject: Re: What’s the point?


Hal Fulton
hal9000@hypermetrics.com

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.

Jason Creighton

···

On Thu, 17 Jul 2003 17:26:14 GMT “Sean O’Dell” sean@REMOVEME.celsoft.com wrote:

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

Yes, I see now that it does.

In Pascal’s case, it wouldn’t have, which is mainly what I was addressing.

Given the above, I can’t see what the point is either (other than what Matz
said).

True, but it doesn’t exist until fred is called:

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…

Nathaniel

<:((><

···

Jim Freeze [mailto:jim@freeze.org] wrote:

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. :slight_smile:

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();
}

wrote (more or less):

“Yukihiro Matsumoto” matz@ruby-lang.org schrieb im Newsbeitrag
news:1058453207.121971.1366.nullmailer@picachu.netlab.jp…

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…

Or

Concise and to the point - Matz has a gift. I hope to get it, too.

Why keep Golf just for Perl or Ruby? :slight_smile:

Cheers,
Euan
Gawnsoft: http://www.gawnsoft.co.sr
Symbian/Epoc wiki: http://html.dnsalias.net:1122
Smalltalk links (harvested from comp.lang.smalltalk) http://html.dnsalias.net/gawnsoft/smalltalk

···

On Thu, 17 Jul 2003 17:05:56 +0200, “Robert Klemme” bob.news@gmx.net

[snippage]

Here’s an idea.

class CrossPlatform
def unix
def meth1 #…
def meth2 #…
def meth3 #…
end

def windows
def meth1 #…
def meth2 #…
def meth3 #…
end
end

obj = CrossPlatform.new
case this_os
when “Windows”
obj.windows
when “Unix”
obj.unix
end

Just a random thought.

Hal

···

----- Original Message -----
From: “Nathaniel Talbott” nathaniel@talbott.ws
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, July 17, 2003 12:30 PM
Subject: Re: What’s the point?

Jim Freeze [mailto:jim@freeze.org] wrote:

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…


Hal Fulton
hal9000@hypermetrics.com

“Chad Fowler” chad@ns1.chadfowler.com wrote in message
news:Pine.LNX.4.44.0307171413400.21595-100000@ns1.chadfowler.com

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. :slight_smile:

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

“Hal E. Fulton” hal9000@hypermetrics.com wrote in

Here’s an idea.

class CrossPlatform
def unix

Currently (ruby 1.8.0 (2003-07-17 [i386-mswin32]) your example
does work like this.

···

class A; end
class B; end

class CrossPlatform
class << self
def unix
def meth1; p “u1” end
def meth2; p “u2” end
end
end

def self.windows
def meth1; p “w1” end
def meth2; p “w2” end
end

def A.bla
def meth3; p “A.bla” end
end

def bla
def meth4; p “CrossPlatform.bla” end
end
end

obj = B.new
CrossPlatform.windows
obj.meth1

CrossPlatform.unix
obj.meth2

A.bla
obj.meth3

A.new.meth3

CrossPlatform.new.bla
obj.meth4


“w1”
“u2”
“A.bla”
“A.bla”
“CrossPlatform.bla”

/Christoph