Problems with throw/catch (newbie)

I'm trying to do something that I think would be pretty trivial. I've
read in an external file as an array. I want to parse the array of
lines, and set a line number as a variable if the line matches a certain
pattern. The file is rather long, so I want to break out of the loop
once I've made the match.

I've tried this a number of different ways, and they either don't work,
or I get some JumpError (which is incomprehensible to my newbie mind).
I'm still deeply in the "suck period" of learning Ruby (and
transitioning from O-O Fortran 95 and UNIX scripting), so I'm struggling
quite a bit.

I'm running Ruby 1.8.6 through Eclipse.

Where I'm at is the following (and this is just the latest in a series
of varieties trying to make the stupid thing work):

···

============================

inputFile = File.open( "filename","r" )
inputArray = inputFile.readlines
counts = 1
xcob3cArray.each catch(:breakout) do |line|
      line_number = counts
      throw(:breakout) "$counts" if ( line.lstrip =~ /^(11))/ )
      counts = counts + 1
end
line_number = $counts

============================

Any help would be greatly appreciated!!
--
Posted via http://www.ruby-forum.com/.

If your file is really that large you'd probably rather want to read it line by line and not in a single Array.

# untested
def search file, rx
   File.open file do |io|
     io.each do |line|
       return io.lineno if rx =~ line
     end
   end
end

Kind regards

  robert

···

On 27.07.2008 18:52, Thomas Luedeke wrote:

I'm trying to do something that I think would be pretty trivial. I've
read in an external file as an array. I want to parse the array of
lines, and set a line number as a variable if the line matches a certain
pattern. The file is rather long, so I want to break out of the loop
once I've made the match.

I've tried this a number of different ways, and they either don't work,
or I get some JumpError (which is incomprehensible to my newbie mind).
I'm still deeply in the "suck period" of learning Ruby (and
transitioning from O-O Fortran 95 and UNIX scripting), so I'm struggling
quite a bit.

I'm running Ruby 1.8.6 through Eclipse.

Where I'm at is the following (and this is just the latest in a series
of varieties trying to make the stupid thing work):

============================

inputFile = File.open( "filename","r" )
inputArray = inputFile.readlines
counts = 1
xcob3cArray.each catch(:breakout) do |line|
      line_number = counts
      throw(:breakout) "$counts" if ( line.lstrip =~ /^(11))/ )
      counts = counts + 1
end
line_number = $counts

============================

Any help would be greatly appreciated!!

Thomas Luedeke wrote:

inputFile = File.open( "filename","r" )
inputArray = inputFile.readlines
counts = 1
xcob3cArray.each catch(:breakout) do |line|
      line_number = counts
      throw(:breakout) "$counts" if ( line.lstrip =~ /^(11))/ )
      counts = counts + 1
end
line_number = $counts

============================

Any help would be greatly appreciated!!

Definitely, evaluating the file a line at a time will be more efficient,
but it's also worth noting that there is an error in your thinking about
the 'each' block.

First, Ruby blocks don't work like Java iterators. That is, you can't
use 'catch' and 'throw' the way that you have. Second, it is good
programing practice to reserve 'throw's and 'catch'es for
honest-to-goodness errors (this isn't just Ruby specific either).

In your case, you'd want to use 'break' ('next' is also good for loops).
So, combining Robert's advice with mine (and another tip or two for
conciseness and efficiency :wink: ), you'd have:

line_number = 0
File.open(inputFile) do |file|
  file.each_line do |line|
    line_number += 1
    break if line =~ /^\s*(11)/
  end
end

Cheers, and happy coding!

-Josh

···

--
Posted via http://www.ruby-forum.com/\.

Joshua Ballanco wrote:

First, Ruby blocks don't work like Java iterators. That is, you can't use 'catch' and 'throw' the way that you have. Second, it is good programing practice to reserve 'throw's and 'catch'es for honest-to-goodness errors (this isn't just Ruby specific either).

There's nothing wrong with using catch/throw as a control flow construct, if you need it. For example: breaking out of nested loops.

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Joel VanderWerf wrote:

Joshua Ballanco wrote:

First, Ruby blocks don't work like Java iterators. That is, you can't
use 'catch' and 'throw' the way that you have. Second, it is good
programing practice to reserve 'throw's and 'catch'es for
honest-to-goodness errors (this isn't just Ruby specific either).

There's nothing wrong with using catch/throw as a control flow
construct, if you need it. For example: breaking out of nested loops.

Ah, the classic debate...this could go on forever....

There are a number of reasons not to use throw/catch for flow control.
One reason is the overhead involved. Another reason is that there's the
risk of someone else catching your throw. Yet another is that if, for
whatever reason, your throw is not caught, it will percolate all the way
up and kill your process.

If you're in a nested loop, it would be better to have a flag and set it
when you want to break out entirely. Better yet, use a 'goto'.

Yes, that's right, 'goto' can be useful. Those teachers that taught you
you'd go to programmer hell if you used it weren't telling the whole
truth.

···

--
Posted via http://www.ruby-forum.com/\.

Joshua Ballanco wrote:

Yes, that's right, 'goto' can be useful.

Every processor instruction set I've seen has an unconditional jump
opcode or equivalent. E.g. x86 assembler uses JMP. If it's there we
should us it. :wink:

Dave

···

--
Posted via http://www.ruby-forum.com/\.

Sorry, but this is ridiculous. Assembler and Ruby are two completely
different pairs of shoes.

In this case "return" or "break" are far more appropriate IMHO. throw
/ catch would also work (module caveats that have been mentioned) but
I always feel reluctant about using those when they are not needed
since they resemble exceptions too closely.

Cheers

robert

···

2008/7/28 Dave Bass <davebass@musician.org>:

Joshua Ballanco wrote:

Yes, that's right, 'goto' can be useful.

Every processor instruction set I've seen has an unconditional jump
opcode or equivalent. E.g. x86 assembler uses JMP. If it's there we
should us it. :wink:

--
use.inject do |as, often| as.you_can - without end

Robert Klemme wrote:

···

2008/7/28 Dave Bass <davebass@musician.org>:

Joshua Ballanco wrote:

Yes, that's right, 'goto' can be useful.

Every processor instruction set I've seen has an unconditional jump
opcode or equivalent. E.g. x86 assembler uses JMP. If it's there we
should us it. :wink:

Sorry, but this is ridiculous. Assembler and Ruby are two completely
different pairs of shoes.

In this case "return" or "break" are far more appropriate IMHO. throw
/ catch would also work (module caveats that have been mentioned) but
I always feel reluctant about using those when they are not needed
since they resemble exceptions too closely.

Cheers

robert

What is annoying to me is that even Fortran 95 has the capability (using
"EXIT [construct] name") to get out of deeply nested loops. Why does
Ruby force you to use catch/throw (which intuitively seems like
exception handling to me). My example above used catch/throw for a
single loop, but the reason I asked is that I anticipate having to break
out of more deeply nested loops.
--
Posted via http://www.ruby-forum.com/\.

The biggest argument against catch/throw is that, when one looks at
existing ruby code, authors using it are in a minority compared to
return/break/each/loop/begin/rescue users. Or it other words, it is seen
less often.

···

--
Posted via http://www.ruby-forum.com/.

Interestingly I cannot remember having to break from a nested loop.
It must be a very rare situation in my programming. I can think of a
number of reasons why that is:

a) my programming style, namely to keep methods short and refactor
b) the types of problems I build solutions for

Not sure what it is in fact but I tend to believe that often this
breaking from nested loop can easily be done via a "return" or having
appropriate loop conditions. For example, this is an idiom I often
use in other languages and it also works well for arbitrarily nested
loops:

def look_for x
  @items.each do |it|
    return it if x == it
  end
  nil
end

Maybe this helps.

Kind regards

robert

···

2008/7/28 Thomas Luedeke <thomas.luedeke@areva.com>:

What is annoying to me is that even Fortran 95 has the capability (using
"EXIT [construct] name") to get out of deeply nested loops. Why does
Ruby force you to use catch/throw (which intuitively seems like
exception handling to me). My example above used catch/throw for a
single loop, but the reason I asked is that I anticipate having to break
out of more deeply nested loops.

--
use.inject do |as, often| as.you_can - without end