nested methods good or bad design

J

John Maclean

=begin
Hey chaps,

Is it bad practice to have nested methods? I'm sure that it would
result in messey/cluttered code. Does any one actually code like that
at all? Not really -essential- as everything is working, (even better
than), as expected without nested methods. Just would be nice to know
what the gurus andmy peers think on this one.

- jjm
=end

class Foo
def initialize(this, that, the_other)
@this = this
..
end

def method_1?
# here I check for some criteria
if %x[some_command] == "some criteria"
@this = true
end

# every other method from here on depends on @this == true. Would be nice to be able to skip the remained of the code if @this != true

def method_2
# do all of this stuff if @this = true
end
 
A

ara.t.howard

def method_1?
# here I check for some criteria
if %x[some_command] == "some criteria"
@this = true
end

# every other method from here on depends on @this == true. Would
be nice to be able to skip the remained of the code if @this != true

def method_2
# do all of this stuff if @this = true
end

this is *exactly* what closures are for

def method_1
method_2 = @this ? lambda{ p 'yup' } : lambda{ p 'nope' }
method_3 = @this ? lambda{ p 'a' } : lambda{ p 'b' }

method_2.call
method_3.call

regards.

a @ http://codeforpeople.com/
 
C

Charles Oliver Nutter

John said:
=begin
Hey chaps,

Is it bad practice to have nested methods? I'm sure that it would
result in messey/cluttered code. Does any one actually code like that
at all? Not really -essential- as everything is working, (even better
than), as expected without nested methods. Just would be nice to know
what the gurus andmy peers think on this one.

- jjm
=end

class Foo
def initialize(this, that, the_other)
@this = this
..
end

def method_1?
# here I check for some criteria
if %x[some_command] == "some criteria"
@this = true
end

# every other method from here on depends on @this == true. Would be nice to be able to skip the remained of the code if @this != true

def method_2
# do all of this stuff if @this = true
end

If you intend to skip defining those other methods, you need a state
variable (constant, class var, whatever) that has a lifespan longer than
that of the instances of your class. @this is going to be nil until set
by method_1?, which can only be called against an instance of Foo, which
can only happen after Foo has already been defined along with the
methods in Foo. But you can put such logic in the Foo class object to
achieve the effect you're looking for:

class Foo
class << self
def method_1?
# here I check for some criteria
if %x[some_command] == "some criteria"
true
else
false
end
end
end

if method_1?
def method_2
# etc
end
end
end

method_2 will only be defined if your criteria is met.

- Charlie
 
C

Charles Oliver Nutter

ara.t.howard said:
this is *exactly* what closures are for

def method_1
method_2 = @this ? lambda{ p 'yup' } : lambda{ p 'nope' }
method_3 = @this ? lambda{ p 'a' } : lambda{ p 'b' }

method_2.call
method_3.call

method_2 and method_3 are not long-lived, so if OP intention was to
conditionally define methods, closures are a rather orthogonal concept.

- Charlie
 
K

krusty.ar

=begin
Hey chaps,

Is it bad practice to have nested methods? I'm sure that it would
result in messey/cluttered code. Does any one actually code like that
at all? Not really -essential- as everything is working, (even better
than), as expected without nested methods. Just would be nice to know
what the gurus andmy peers think on this one.

I'm not sure I understand completely, but how is having a variable (or
any other object) laying around representing that the system can call
method2 is cleaner than:

def method1
if criteria
def method 2
##...
end
end
end

?

I find that easier to follow than:

def method1
if criteria
#set some flag
end
end

##.. more code

##check the flag

def method2
##...
end

The only way that the first alternative could get messy is with very
long methods, wich you should avoid anyway.

Lucas.
 
T

ThoML

Is it bad practice to have nested methods?

Like Eiffel, Smalltalk, Java, Ruby doesn't have nested methods
unlike ... uhm, Python, Scheme etc. (Everything IIRC and AFAIK which
doesn't mean much ATM. :)

Example:

def a
def b
p 1
end
b
end

a
=> 1
b
=> 1

a and b are defined at the same level. This trick can be used to
dynamically (re)define methods at runtime and can be handy at times.

You could create a normal method and make that private.
 
K

krusty.ar

def a
    def b
        p 1
    end
    b
end

a
=> 1
b
=> 1

But this has the additional (somewhat usefull) effect that calling b
before a will give an error. Maybe I'm not understanding what you are
reffering to as nested methods or "same level", what can you do in
phyton or scheme that behaves different from this?

Lucas.

Lucas.
 
T

ThoML

Maybe I'm not understanding what you are
reffering to as nested methods or "same level", what can you do in
phyton or scheme that behaves different from this?
.... def b():
.... print(1)
.... b()
....Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined

b() is not accessible from outside of a().
 
T

ThoML

b() is not accessible from outside of a().
you have to execute it to make the definition occur

This referred to the Python counter example -- because KA asked how
Python/Scheme/... are different in this respect.
 
K

krusty.ar

...     def b():
...         print(1)
...     b()
...>>> a()
1

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined

b() is not accessible from outside of a().

Y get it, it's as if each method defines a namespace, can
youdosomething like a()::b() from ouside a?

Lucas.
 
T

ThoML

Y get it, it's as if each method defines a namespace, can
youdosomething like a()::b() from ouside a?

I'd say no. You'd probably have to ask this on a python list for more
details. I don't think this would make much sense though:

--> def a(x, y):
.... def b(z):
.... return z * y
.... return x * b(4)
....
--> a(2, 3)
24

What should a::b(10) return if this were possible?

BTW I personally like nested functions/methods. This was/is one thing
I miss in ruby.

Anyway, I think though the OP asked for something different. The
problem with that would be that the proposed code IMHO is that the
definition of a method for all objects of that class would depend on
the value of an instance variable of one specific object. Ara's
solution or instance methods would solve this. If I'm not mistaken,
another approach could be:

class A
def a(x)
if x == 0
def self.b
10
end
else
def self.b
20
end
end
self
end
end

o1 = A.new.a(0)
o2 = A.new.a(1)
p o2.b, o1.b
=> [20, 10]
 
K

krusty.ar

I'd say no. You'd probably have to ask this on a python list for more
details. I don't think this would make much sense though:

--> def a(x, y):
...     def b(z):
...         return z * y
...     return x * b(4)
...
--> a(2, 3)
24

What should a::b(10) return if this were possible?

I was asking out of mere curiosity, but in any case it should be
something like a(2,3)::b(4), but it probably doesn't make sense. With
respect to de OP, I still find it a good practice, including your
correction about the instance variable.

Lucas.
 
J

John Maclean

Um, thanks for all of the replies chaps. Most of it makes sense. In
essence all I wanted to do was speed things up and so the first method
checked a server for something.=20

All of the other methods check an instance variable, (from the
first method), and progress with more operations given the value of that
iv.=20

Some of the methods __are__ long and that's why I asked if it was good
practice to ask if nested methods are used in the field. Would make
sense for smaller methods I guess but not for 70+ lines.=20

Not tried closures yet - just got into profiling, tracing and
debugging to see how I can speed things up.

Many thanks for all of your insight. By the way - this Ruby stuff is
bloody addictive. Not been so excited for a long time, especially when
stuff "works".=20

- jjm
 
T

ThoML

the first method checked a server for something.
All of the other methods check an instance variable

I don't know when you check the server. Maybe something like this
would be a viable solution (#create could check the server):

class A
def self.create(x)
case x
when 0
A1.new(x)
else
A2.new(x)
end
end

def initialize(x)
@x = x
end
end

class A1 < A
def f
nil
end
end

class A2 < A
def f
20 + @x
end
end

p A.create(0).f
=> nil
p A.create(1).f
=> 21
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top