Generalized break?

I hate to bring up possible language changes, since there is
so much of that going around.

Matz, if this is stupid, just tell me so.

I’ve sometimes wished for a “break” that would work in (almost) any
context – one that would do “the sensible thing” instead of just
giving an error saying you can’t do a break here.

Two examples are:

  1. A long string, possibly multiline/multi-statement, is being
    evaled. I want the capability to abort the eval.

  2. I have a mild dislike for the idiom if $0 == FILE (lines) end
    – because I always indent inside an if, and I don’t want to indent,
    and I really just want to say: break if $0 != FILE

In both these contexts, I initially tried exit. Of course, that
doesn’t work – it exits the entire program. A “return” seems like
the next choice, but that only makes sense within a method.

There’s no proper way to do this kind of thing, as far as I can
see.

Thoughts?

Hal

I’ve sometimes wished for a “break” that would work in (almost) any
context – one that would do “the sensible thing” instead of just
giving an error saying you can’t do a break here.

Two examples are:

  1. A long string, possibly multiline/multi-statement, is being
    evaled. I want the capability to abort the eval.

  2. I have a mild dislike for the idiom if $0 == FILE (lines) end
    – because I always indent inside an if, and I don’t want to indent,
    and I really just want to say: break if $0 != FILE

I actually would like that too, especially for #2, since it avoids lots
of nasty nesting for unit tests and such.

In both these contexts, I initially tried exit. Of course, that
doesn’t work – it exits the entire program. A “return” seems like
the next choice, but that only makes sense within a method.

I think break makes sense here, and I’d use it if it were available.

There’s no proper way to do this kind of thing, as far as I can
see.

Well, maybe not proper, but here is a way to do it. :wink:

#!/usr/bin/ruby

puts “File loaded.”

if $0 == FILE then puts <<-EOF ; end

look, no indent, and we’re not nested in an if! =)

puts “File called directly.”

EOF

···

On Thursday 04 December 2003 3:13 pm, Hal Fulton wrote:


Wesley J. Landaker - wjl@icecavern.net
OpenPGP FP: 4135 2A3B 4726 ACC5 9094 0097 F0A9 8A4C 4CD6 E3D2

Hal Fulton wrote:

I hate to bring up possible language changes, since there is
so much of that going around.

Matz, if this is stupid, just tell me so.

I’ve sometimes wished for a “break” that would work in (almost) any
context – one that would do “the sensible thing” instead of just
giving an error saying you can’t do a break here.

Two examples are:

  1. A long string, possibly multiline/multi-statement, is being
    evaled. I want the capability to abort the eval.

  2. I have a mild dislike for the idiom if $0 == FILE (lines) end
    – because I always indent inside an if, and I don’t want to indent,
    and I really just want to say: break if $0 != FILE

In both these contexts, I initially tried exit. Of course, that
doesn’t work – it exits the entire program. A “return” seems like
the next choice, but that only makes sense within a method.

There’s no proper way to do this kind of thing, as far as I can
see.

If you just do not want to indent, I would suggest

if $0 == FILE
eval DATA.readlines.join(“\n”), binding, FILE
end
END
puts “HELLO”

It looks ugly and excessive, I agree. It also has problems with error
reporting, whatever line number it shows you have to add 4 (in this
particular case) to it mentally.

It works, however :wink:

Gennady.

···

Thoughts?

Hal

Hal Fulton wrote:

  1. I have a mild dislike for the idiom if $0 == FILE (lines) end
    – because I always indent inside an if, and I don’t want to indent,
    and I really just want to say: break if $0 != FILE

This seems to work:

=== x.rb ===
puts “loading x.rb”

alias old_load load
def load(*args)
catch :break_from_load do
old_load(*args)
end
end

throw :break_from_load unless FILE == $0

puts “a”

load(FILE)

puts “b”

···

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

Date: Fri, 5 Dec 2003 07:13:04 +0900
From: Hal Fulton hal9000@hypermetrics.com
Newsgroups: comp.lang.ruby
Subject: Generalized break?

I hate to bring up possible language changes, since there is
so much of that going around.

Matz, if this is stupid, just tell me so.

I’ve sometimes wished for a “break” that would work in (almost) any
context – one that would do “the sensible thing” instead of just
giving an error saying you can’t do a break here.

Two examples are:

  1. A long string, possibly multiline/multi-statement, is being
    evaled. I want the capability to abort the eval.

catch/throw is pretty general:

this works:

code = <<-code
if true
def method
42
end
if not false
if true
loop do
p method
throw :bail if rand < 0.5
end
end
end
end
code

def nesting code
eval code
end

catch :bail do
nesting code
end

  1. I have a mild dislike for the idiom if $0 == FILE (lines) end
    – because I always indent inside an if, and I don’t want to indent,
    and I really just want to say: break if $0 != FILE

agreed.

how about something like

TEST

for this?

In both these contexts, I initially tried exit. Of course, that
doesn’t work – it exits the entire program. A “return” seems like
the next choice, but that only makes sense within a method.

There’s no proper way to do this kind of thing, as far as I can
see.

Thoughts?

Hal

-a

···

On Fri, 5 Dec 2003, Hal Fulton wrote:

ATTN: please update your address books with address below!

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

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
STP :: Solar-Terrestrial Physics Data | NCEI
NGDC :: http://www.ngdc.noaa.gov/
NESDIS :: http://www.nesdis.noaa.gov/
NOAA :: http://www.noaa.gov/
US DOC :: http://www.commerce.gov/

The difference between art and science is that science is what we
understand well enough to explain to a computer.
Art is everything else.
– Donald Knuth, “Discover”

/bin/sh -c ‘for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done’
===============================================================================

Hi,

I’ve sometimes wished for a “break” that would work in (almost) any
context – one that would do “the sensible thing” instead of just
giving an error saying you can’t do a break here.

“break” or jump in general requires destination. If you want
something like “generalized break”, you have to define the destination
for each context. Basically, catch/throw is prepared for that
purpose.

  1. A long string, possibly multiline/multi-statement, is being
    evaled. I want the capability to abort the eval.

Use catch/throw.

  1. I have a mild dislike for the idiom if $0 == FILE (lines) end
    – because I always indent inside an if, and I don’t want to indent,
    and I really just want to say: break if $0 != FILE

I think it’s not a good idea that preparing single syntax construct to
serve too many purpose. I admit “$0 != FILE” hack is ugly, but it
should be solved by some other way than "generalized break.

						matz.
···

In message “Generalized break?” on 03/12/05, Hal Fulton hal9000@hypermetrics.com writes:

Err, that just prints things out, nevermind. (I wasn’t serious anyway :wink:

···

On Thursday 04 December 2003 3:40 pm, Wesley J Landaker wrote:

Well, maybe not proper, but here is a way to do it. :wink:

#!/usr/bin/ruby

puts “File loaded.”

if $0 == FILE then puts <<-EOF ; end

look, no indent, and we’re not nested in an if! =)

puts “File called directly.”

EOF


Wesley J. Landaker - wjl@icecavern.net
OpenPGP FP: 4135 2A3B 4726 ACC5 9094 0097 F0A9 8A4C 4CD6 E3D2

Joel VanderWerf wrote:

Hal Fulton wrote:

  1. I have a mild dislike for the idiom if $0 == FILE (lines) end
    – because I always indent inside an if, and I don’t want to indent,
    and I really just want to say: break if $0 != FILE

This seems to work:

=== x.rb ===
puts “loading x.rb”

alias old_load load
def load(*args)
catch :break_from_load do
old_load(*args)
end
end

throw :break_from_load unless FILE == $0

puts “a”

load(FILE)

puts “b”

You get the following error when you ‘require’ this file:

irb(main):001:0> require ‘x’
loading x.rb
NameError: uncaught throw break_from_load' from ./x.rb:11:in throw’
from ./x.rb:11
from (irb):1:in `require’
from (irb):1
irb(main):002:0>

Gennady.

Ooohh, I like that! =)

(Hmmm… can we implement it in ruby as is? … using the eval hack
posted earlier in this thread sort of works, although this is a bit
ugly):

— test.rb —
#!/usr/bin/ruby

def TEST(file)
if $0 == file
eval DATA.readlines.join(“\n”), binding, file
end
end

— demo.rb —
#!/usr/bin/ruby

#!/usr/bin/ruby
require ‘test’

puts “1”

TEST(FILE)
END

puts “2”

Then:
$ ./demo.rb
1
2
$ irb
irb(main):001:0> require ‘demo’
1
=> true

Not sure how to get around passing FILE in, or having END there
as well…

···

On Thursday 04 December 2003 5:32 pm, Ara.T.Howard wrote:

  1. I have a mild dislike for the idiom if $0 == FILE (lines)
    end – because I always indent inside an if, and I don’t want to
    indent, and I really just want to say: break if $0 != FILE

agreed.

how about something like

TEST

for this?


Wesley J. Landaker - wjl@icecavern.net
OpenPGP FP: 4135 2A3B 4726 ACC5 9094 0097 F0A9 8A4C 4CD6 E3D2

I’ve sometimes wished for a “break” that would work in (almost) any
context – one that would do “the sensible thing” instead of just
giving an error saying you can’t do a break here.

“break” or jump in general requires destination. If you want
something like “generalized break”, you have to define the destination
for each context. Basically, catch/throw is prepared for that
purpose.

However sometimes having to define the destination is very inconvenient,
as in

  1. I have a mild dislike for the idiom if $0 == FILE (lines) end
    – because I always indent inside an if, and I don’t want to indent,
    and I really just want to say: break if $0 != FILE

I think it’s not a good idea that preparing single syntax construct to
serve too many purpose. I admit “$0 != FILE” hack is ugly, but it
should be solved by some other way than "generalized break.

Would it be possible to wrap each file/evaluated string in an implicit

catch(:END_INTERPRETATION) do # a better name is 90% of the thing :slight_smile:

end

?

···

On Fri, Dec 05, 2003 at 12:05:20PM +0900, Yukihiro Matsumoto wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

“You, sir, are nothing but a pathetically lame salesdroid!
I fart in your general direction!”
– Randseed on #Linux

Hi –

···

On Fri, 5 Dec 2003, Wesley J Landaker wrote:

— test.rb —
#!/usr/bin/ruby

def TEST(file)
if $0 == file
eval DATA.readlines.join(“\n”), binding, file
end
end

— demo.rb —
#!/usr/bin/ruby

#!/usr/bin/ruby
require ‘test’

puts “1”

TEST(FILE)
END

puts “2”

Then:
$ ./demo.rb
1
2
$ irb
irb(main):001:0> require ‘demo’
1
=> true

Not sure how to get around passing FILE in, or having END there
as well…

Yeah, I don’t think the solutions where the code comes after END
are really viable. I tend to use DATA to feed to tests, so I don’t
want DATA to be the tests.

David


David A. Black
dblack@wobblini.net

Ooohh, I like that! =3D)

:wink: me too.

Not sure how to get around passing FILE in, or having END there=20
as well…

well, for FILE you could

def TEST (file = FILE)

end

couldn’t you?

-a

···

On Fri, 5 Dec 2003, Wesley J Landaker wrote:

ATTN: please update your address books with address below!

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

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
STP :: Solar-Terrestrial Physics Data | NCEI
NGDC :: http://www.ngdc.noaa.gov/
NESDIS :: http://www.nesdis.noaa.gov/
NOAA :: http://www.noaa.gov/
US DOC :: http://www.commerce.gov/

The difference between art and science is that science is what we
understand well enough to explain to a computer.
Art is everything else.
– Donald Knuth, “Discover”

/bin/sh -c ‘for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done’
===============================================================================

That doesn’t work in this case, because then FILE refers to
“test.rb” instead of “demo.rb”. There is probably a way to get around
that, but I haven’t tried real hard.

···

On Thursday 04 December 2003 8:32 pm, Ara.T.Howard wrote:

On Fri, 5 Dec 2003, Wesley J Landaker wrote:

Ooohh, I like that! =3D)

:wink: me too.

Not sure how to get around passing FILE in, or having END
there=20 as well…

well, for FILE you could

def TEST (file = FILE)

end

couldn’t you?


Wesley J. Landaker - wjl@icecavern.net
OpenPGP FP: 4135 2A3B 4726 ACC5 9094 0097 F0A9 8A4C 4CD6 E3D2

It would be nice to be able to do this in a Ruby file:

main code

TEST

code that will be used if called directly

END

stuff for DATA

Hmmm… on the other hand, most of my ruby files that have unit tests
look like this:

if $0 == FILE or defined? Test::Unit
require ‘test/unit’

class SomeTest < Test::Unit::TestCase
# whatever
end
end

Then, I have something like this in a Makefile:

RUNTESTS=-rtest/unit -e ‘Dir[“*.rb”].each { |f| require f }’
test:
@ruby $(RUNTESTS)

This lets me call a file directly to test it, or have them batched for
regression test running very easily.

I’m not sure a mechanism like TEST would help me in this case
(although, it wouldn’t hurt).

···

On Thursday 04 December 2003 6:59 pm, David A. Black wrote:

Yeah, I don’t think the solutions where the code comes after END
are really viable. I tend to use DATA to feed to tests, so I don’t
want DATA to be the tests.


Wesley J. Landaker - wjl@icecavern.net
OpenPGP FP: 4135 2A3B 4726 ACC5 9094 0097 F0A9 8A4C 4CD6 E3D2