Forum: Ruby Alternatives to methods for large number of nested "ifs"

Posted by Philip Rhoades (Guest)
on 2012-11-16 15:35
(Received via mailing list)
People,

I have an existing script that looks like:

lots of code
.
.
.
if ..
   some lines of code
   if ..
     some lines of code
     if ..
       some lines of code
       if ..
         some lines of code
         if ..
           some lines of code
etc

This makes it difficult to see the overall logic so I want to change it
to something like:

lots of code
.
.
.
if ..
   call something
   if ..
     call something
     if ..
       call something
       if ..
         call something
         if ..
           call something
etc

but if I use methods I will have to pass lots of variables or use
global variables and then it gets clumsy changing everything - is there
some way of simply calling a block of code and then returning to the
same position in the nested "ifs"?

Thanks,

Phil.
--
Philip Rhoades

GPO Box 3411
Sydney NSW  2001
Australia
E-mail:  phil@pricom.com.au
Posted by Robert Klemme (robert_k78)
on 2012-11-16 15:45
(Received via mailing list)
On Fri, Nov 16, 2012 at 3:35 PM, Philip Rhoades <phil@pricom.com.au> 
wrote:
>   if ..
>     some lines of code
>     if ..
>       some lines of code
>       if ..
>         some lines of code
>         if ..
>           some lines of code
> etc
>
> This makes it difficult to see the overall logic

I can believe *that*.

>     if ..
>       call something
>       if ..
>         call something
>         if ..
>           call something
> etc

That does not seem much better to me.  Why do you need such a
structure of code?  Can you be more specific about what you are doing
there?  Maybe a completely different structure of the code is even
better.

> but if I use methods I will have to pass lots of variables or use global
> variables and then it gets clumsy changing everything - is there some way of
> simply calling a block of code and then returning to the same position in
> the nested "ifs"?

I don't think there is.  Unless, maybe, if you declare all local
variables at the beginning of the method, followed by a whole bunch of
Procs which you call where "something" is written.  I doubt though
that this will be more readable.

Kind regards

robert
Posted by botp (Guest)
on 2012-11-16 16:50
(Received via mailing list)
On Fri, Nov 16, 2012 at 10:35 PM, Philip Rhoades <phil@pricom.com.au> 
wrote:
> etc
try a chain, eg,

$ cat test.rb ; echo "--output--"; ruby test.rb
[
    [->{true},->{p "one"}],
    [->{1==1}, ->{p "two"}],
    [->{false},->{p "no see"}],
    [->{true},->{p "wont see light"}],
].each do |condition, func|
    break unless condition.call
    func.call
end

--output--
"one"
"two"

best regards -botp
Posted by Brian Candler (candlerb)
on 2012-11-16 19:15
Philip Rhoades wrote in post #1084734:
> I have an existing script that looks like:
>
> lots of code
> .
> .
> .
> if ..
>    some lines of code
>    if ..
>      some lines of code
>      if ..
>        some lines of code
>        if ..
>          some lines of code
>          if ..
>            some lines of code
> etc
>
> This makes it difficult to see the overall logic

stick it in a method:

def mymethod
  return unless ...
  some lines of code
  return unless ...
  some lines of code
end

lots of code
.
.
mymethod

But if you must keep it within the same scope (lots of local variables 
as you say, that you don't want to pass as arguments), then throw/catch 
is another option.

lots of code
.
.
catch(:done) do
  throw :done unless ...
  some lines of code
  throw :done unless ...
  some lines of code
end
Posted by Joel Pearson (virtuoso)
on 2012-11-16 20:51
Wouldn't a case statement work for this kind of thing?
Posted by Henry Maddocks (Guest)
on 2012-11-16 23:32
(Received via mailing list)
On 17/11/2012, at 7:15 AM, Brian Candler wrote:



>  throw :done unless ...
>  some lines of code
> end


Don't use exceptions for flow control.

Henry
Posted by Henry Maddocks (Guest)
on 2012-11-16 23:41
(Received via mailing list)
On 17/11/2012, at 8:51 AM, Joel Pearson wrote:

> Wouldn't a case statement work for this kind of thing?

case statements are more of an if..else replacement rather than nested 
ifs. If you can refactor the code to use case statements then that's a 
good start because from there you can replace the branches with calls to 
objects.

Nested ifs are really hard to get rid of without major code refactoring.

Henry
Posted by unknown (Guest)
on 2012-11-16 23:53
(Received via mailing list)
Am 16.11.2012 23:30, schrieb Henry Maddocks:
>> catch(:done) do
>>   throw :done unless ...
>>   some lines of code
>>   throw :done unless ...
>>   some lines of code
>> end
>
>
> Don't use exceptions for flow control.
>
> Henry

But throw/catch has nothing to do with exceptions.
Posted by Arlen Cuss (Guest)
on 2012-11-17 03:26
(Received via mailing list)
> >
> >
> > Don't use exceptions for flow control.
> >
> > Henry
>
> But throw/catch has nothing to do with exceptions.
>


Indeed — throw/catch is *for* flow control.
Posted by tamouse mailing lists (Guest)
on 2012-11-17 04:31
(Received via mailing list)
On Fri, Nov 16, 2012 at 9:50 AM, botp <botpena@gmail.com> wrote:
>     func.call
> end
>
> --output--
> "one"
> "two"
>
> best regards -botp
>

That, right there, is idiomatic ruby.
Posted by Henry Maddocks (Guest)
on 2012-11-17 04:34
(Received via mailing list)
On 17/11/2012, at 11:41 AM, sto.mar@web.de wrote:

>>> .
>> Henry
>
> But throw/catch has nothing to do with exceptions.

Sorry, language context switch failure.

Henry
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.