Ideas for replacing $0==__FILE__

I’ve accepted now that my “generalized break” was a bad idea. In
an eval context, I’ll probably just define a “quit” method that
will throw :quit and that will be fine.

I’m thinking (again) about the idiom “if $0 == FILE” and
trying to come up with viable alternatives.

It seems to me that we don’t really need an “executable” thing
like exit/break/return/quit in this context.

It could just be a “marker” as someone suggested.

My two favorites so far are TEST and MAIN.

As far as I can see, there should be no conflict or interaction
with the END marker.

Comments?

Hal

Do I understand you correctly, Hal?

sample.rb:

#!/usr/bin/ruby

ruby code that won’t be executed

MAIN

code that will normally be

TEST

will run instead if test (or debug?) flag

END

raw data

···

On Saturday 06 December 2003 07:59 pm, Hal Fulton wrote:

It could just be a “marker” as someone suggested.

My two favorites so far are TEST and MAIN.

As far as I can see, there should be no conflict or interaction
with the END marker.

Comments?

We also discussed on IRC having a “-t” flag to the ruby interpreter that
would run a TEST block (like BEGIN or END or at_exit), but TEST
seems even better than that.

···

Hal Fulton (hal9000@hypermetrics.com) wrote:

I’m thinking (again) about the idiom “if $0 == FILE” and
trying to come up with viable alternatives.

It seems to me that we don’t really need an “executable” thing
like exit/break/return/quit in this context.

It could just be a “marker” as someone suggested.

My two favorites so far are TEST and MAIN.

As far as I can see, there should be no conflict or interaction
with the END marker.


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

I’ve recently found that it is sometimes useful to combine a "main"
Ruby program with required modules into a single file. Aside from
being able to deliver the program as a single file, I’ve seen about a
10% improvement to load time. I’m even thinking it would be nice to
have a program to do it for me.

Needless to say, the fact that everybody else in my team was using the
$0 == FILE idiom in their modules was a serious pain initially.

From this perspective, it would be nice to have a mechanism that (1)
is not enabled by default, and especially (2) is easy to parse out.

Do people really consider this idiom to be that useful? Most of the
times I’ve seen it used, it wraps either examples (better done in
separate files, you can have more than one and more complex), or tests
(much better done with Test::Unit).

Steve

T. Onoma wrote:

Do I understand you correctly, Hal?

Sorry, I was unclear.

It’s like this:

#!/usr/bin/ruby
(treat as normal code)
FOO
(execute only if this is the main file, not
a required/loaded file)
END
(any data)

where FOO is some marker, either MAIN or TEST
or something else.

Better?

Hal

Eric Hodel wrote:

···

Hal Fulton (hal9000@hypermetrics.com) wrote:

I’m thinking (again) about the idiom “if $0 == FILE” and
trying to come up with viable alternatives.

It seems to me that we don’t really need an “executable” thing
like exit/break/return/quit in this context.

It could just be a “marker” as someone suggested.

My two favorites so far are TEST and MAIN.

As far as I can see, there should be no conflict or interaction
with the END marker.

We also discussed on IRC having a “-t” flag to the ruby interpreter that
would run a TEST block (like BEGIN or END or at_exit), but TEST
seems even better than that.

Are we talking about the same thing? In my scheme, if foo.rb had
a TEST_ section, it would be run simply by ruby foo.rb (and
not run if foo.rb was require’d).

How does that relate to the -t idea (which I don’ quite get)?

Hal

I’ve recently found that it is sometimes useful to combine a “main” Ruby
program with required modules into a single file.

I’m not entirely sure what you mean here. Can we have an example?

[…]

Do people really consider this idiom to be that useful? Most of the
times I’ve seen it used, it wraps either examples (better done in
separate files, you can have more than one and more complex), or tests
(much better done with Test::Unit).

I commonly wrap Test::Unit tests in ‘if $0 == FILE’. It’s easier to
edit and execute the tests when they’re in the same file. It’s less files
in the distribution and no ‘how do I include the library in the library
path from the unit test file?’ hassles.

Concerning the idiom itself, I initially thought it ugly and pondered the
benefit of a “main” function (i.e. at the top level, def main(*args)).
Having come to appreciate the importance of runtime in Ruby, though, I now
think it is appropriate for programmers to be aware of, and take control
of, what happens when their files are loaded, and in what context.
Therefore I find the idiom aesthetically unappealing but conceptually
acceptable.

Given this, I have little taste for the proposed MAIN, TEST, etc.
directives.

Gavin

Most of my modules have

if $0 == FILE then
require ‘test/unit’

end

I wouldn’t mind replacing this with a block like:

TEST {
require ‘test/unit’

}

-austin

···

On Thu, 11 Dec 2003 09:52:17 +0900, Steven Lumos wrote:

From this perspective, it would be nice to have a mechanism that (1)
is not enabled by default, and especially (2) is easy to parse out.
Do people really consider this idiom to be that useful? Most of the
times I’ve seen it used, it wraps either examples (better done in
separate files, you can have more than one and more complex), or tests
(much better done with Test::Unit).


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2003.12.10
* 22.35.11

Steve Lumos saith:

$0 == __FILE__ idiom

Do people really consider this idiom to be *that* useful? Most of the
times I've seen it used, it wraps either examples (better done in
separate files, you can have more than one and more complex), or tests
(*much* better done with Test::Unit).

I've found it very useful for my own unit-testing using Test::Unit. Now,
being a Ruby nuby, I haven't absorbed what might have come before about
this, but I set up my unit-testable Ruby library files as executables --
invoke them directly to run the unit tests, and the above idiom guards the
test code.

Others are welcome to point me to current community thought (and working
code :slight_smile: on how to do this. This being Ruby not Perl, there should I
guess be only One Way To Do This. :wink:

        Joseph Beckenbach
        lead XP tester, Eidogen Inc.

So you’re just suggesting that FOO be effectively the same as

if $0 == FILE

end

Yes?

T.

···

On Saturday 06 December 2003 08:29 pm, Hal Fulton wrote:

#!/usr/bin/ruby
(treat as normal code)
FOO
(execute only if this is the main file, not
a required/loaded file)
END
(any data)

where FOO is some marker, either MAIN or TEST
or something else.

Better?

Kind of like this idea too. Basically what Eric is suggesting is that if you
have an ruby file like, example.rb:

# normal code here

SHELL # like, if $0 = FILE

# shell execution code here

TEST

# test code here

END

raw data here

If one were to do

% ruby -t example.rb

it would run the code in the TEST seciton rather than the SHELL
section.

I can also think of another good section CGI :wink:

T.

···

On Wednesday 10 December 2003 09:15 pm, Hal Fulton wrote:

Are we talking about the same thing? In my scheme, if foo.rb had
a TEST_ section, it would be run simply by ruby foo.rb (and
not run if foo.rb was require’d).

How does that relate to the -t idea (which I don’ quite get)?

We also discussed on IRC having a “-t” flag to the ruby interpreter that
would run a TEST block (like BEGIN or END or at_exit), but TEST
seems even better than that.

Are we talking about the same thing? In my scheme, if foo.rb had
a TEST_ section, it would be run simply by ruby foo.rb (and
not run if foo.rb was require’d).

This is different than your use.

How does that relate to the -t idea (which I don’ quite get)?

If you add -t to the ruby interpreter (ruby -t foo.rb) then TEST
get run when ruby exits. ($TEST would also be set like -d sets $DEBUG).

···

Hal Fulton (hal9000@hypermetrics.com) wrote:


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

T. Onoma wrote:

···

On Saturday 06 December 2003 08:29 pm, Hal Fulton wrote:

#!/usr/bin/ruby
(treat as normal code)
FOO
(execute only if this is the main file, not
a required/loaded file)
END
(any data)

where FOO is some marker, either MAIN or TEST
or something else.

Better?

So you’re just suggesting that FOO be effectively the same as

if $0 == FILE

end

Yes?

Yes.

No difference in function, just a little prettier/clearer
and no need to indent or to remember the closing end.

Hal

Hm. I’m not sure I like that. Why not:

TEST {

}

The block is only run with ruby -t …; otherwise it works just like BEGIN
{} and END {} blocks.

-austin

···

On Thu, 11 Dec 2003 06:21:37 +0900, Eric Hodel wrote:

Hal Fulton (hal9000@hypermetrics.com) wrote:

We also discussed on IRC having a “-t” flag to the ruby interpreter
that would run a TEST block (like BEGIN or END or at_exit), but
TEST seems even better than that.
Are we talking about the same thing? In my scheme, if foo.rb had a
TEST_ section, it would be run simply by ruby foo.rb (and not run
if foo.rb was require’d).
This is different than your use.

How does that relate to the -t idea (which I don’ quite get)?
If you add -t to the ruby interpreter (ruby -t foo.rb) then TEST get
run when ruby exits. ($TEST would also be set like -d sets $DEBUG).


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2003.12.10
* 22.33.01

Austin Ziegler wrote:

If you add -t to the ruby interpreter (ruby -t foo.rb) then TEST get
run when ruby exits. ($TEST would also be set like -d sets $DEBUG).

Hm. I’m not sure I like that. Why not:

TEST {

}

The block is only run with ruby -t …; otherwise it works just like BEGIN
{} and END {} blocks.

I like that–in fact, I’d probably use it. What happens if there are
multiple TEST{} blocks (especially in required files)? Do they all get
executed?

···


Jamis Buck
jgb3@email.byu.edu

ruby -h | ruby -e ‘a=;readlines.join.scan(/-(.)[e|Kk(\S*)|le.l(…)e|#!(\S*)/) {|r| a << r.compact.first };puts “\n>#{a.join(%q/ /)}<\n\n”’

That makes good sense to me. Looks cleaner inside and outside the file,
makes the intent much clearer, and I don't have to go around setting stray
executable bits (which CVS often strips off, causing me to write setup
commands for otherwise unchanged library trees).

And no, I haven't seen the need (yet) for a TEST_BEGIN or TEST_END or
NOT_TEST (or equivalent phrasings) in this keyword location.

        Joseph Beckenbach
        lead XP tester, Eidogen Inc.

···

On Thu, 11 Dec 2003 06:21:37 +0900, Eric Hodel wrote:
Why not:

TEST {
  ...
}

The block is only run with ruby -t ...; otherwise it works just like BEGIN
{} and END {} blocks.

This was the original idea.

···

Austin Ziegler (austin@halostatue.ca) wrote:

On Thu, 11 Dec 2003 06:21:37 +0900, Eric Hodel wrote:

Hal Fulton (hal9000@hypermetrics.com) wrote:

We also discussed on IRC having a “-t” flag to the ruby interpreter
that would run a TEST block (like BEGIN or END or at_exit), but
TEST seems even better than that.
Are we talking about the same thing? In my scheme, if foo.rb had a
TEST_ section, it would be run simply by ruby foo.rb (and not run
if foo.rb was require’d).
This is different than your use.

How does that relate to the -t idea (which I don’ quite get)?
If you add -t to the ruby interpreter (ruby -t foo.rb) then TEST get
run when ruby exits. ($TEST would also be set like -d sets $DEBUG).

Hm. I’m not sure I like that. Why not:

TEST {

}

The block is only run with ruby -t …; otherwise it works just like BEGIN
{} and END {} blocks.


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

I would suggest yes. Perhaps -t and -tr (e.g., -t only runs the last; -tr
runs all). What was brought up on #ruby-lang is whether the TEST {} blocks
would be exclusive, overriding normal behaviour. This may be desirable.

-austin

···

On Thu, 11 Dec 2003 12:38:37 +0900, Jamis Buck wrote:

Austin Ziegler wrote:

If you add -t to the ruby interpreter (ruby -t foo.rb) then TEST
get run when ruby exits. ($TEST would also be set like -d sets
$DEBUG).
Hm. I’m not sure I like that. Why not:
TEST {

}
The block is only run with ruby -t …; otherwise it works just like
BEGIN {} and END {} blocks.
I like that–in fact, I’d probably use it. What happens if there are
multiple TEST{} blocks (especially in required files)? Do they all get
executed?


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2003.12.11
* 00.17.28

Austin Ziegler wrote:

I like that--in fact, I'd probably use it. What happens if there are
multiple TEST{} blocks (especially in required files)? Do they all get
executed?

I would not use TEST{} if required files executed any of their TEST{}
blocks under -t: there'd be no way to test just one file. You'd get all
your require'd files unit-test invocations mixed in with yours -- lots of
effort to separate them out for reporting purposes. To avoid this, you'd
have to have *none* of the distribution using TEST{} -- which would defeat
one of the main benefits of having TEST{} in the first place, for general
use.

        Joseph Beckenbach
        lead XP tester, Eidogen Inc.

In article 48744.216.135.205.211.1071165104.squirrel@castle,

Why not:

TEST {

}

The block is only run with ruby -t …; otherwise it works just like BEGIN
{} and END {} blocks.

That makes good sense to me. Looks cleaner inside and outside the file,
makes the intent much clearer, and I don’t have to go around setting stray
executable bits (which CVS often strips off, causing me to write setup
commands for otherwise unchanged library trees).

I like the if $0 == FILE as it is, it’s certainly not ugly enough to
inspire any grumbling from me.

I felt compelled to make a couple of comments:

  • usually I don’t have the executable bits turned on on my libraries,
    and they don’t have #! lines. This means I can’t accidentally run
    them, and end up saying

    ruby foo.rb

    to test foo.rb

    my real programs don’t usually have a .rb suffix (unless I have the
    same thing in multiple languages), do have the executable bit set,
    and have a #! line.

    This scheme works well for me, the only thing I need to remember is
    that when I start a new program without a suffix then gvim doesn’t
    syntax highlight. That’s OK because I usually create an excutable
    file containing

    #!/usr/bin/env ruby

    as my first checkin for a program…

  • In my experience CVS tries to maintain the execute bits as they were
    when you added the file to the repository. See
    Re: cvs chmod ? .
    It is possible to reset the execute bits if you have write access to
    the reporitory’s file store - chmod +x foo.rb,v and then check it out.

Hope this helps,

Mike

···

jrb3@eidogen.com wrote:

On Thu, 11 Dec 2003 06:21:37 +0900, Eric Hodel wrote:

mike@stok.co.uk | The “`Stok’ disclaimers” apply.
http://www.stok.co.uk/~mike/ | GPG PGP Key 1024D/059913DA
mike@exegenix.com | Fingerprint 0570 71CD 6790 7C28 3D60
http://www.exegenix.com/ | 75D2 9EC4 C1C0 0599 13DA