Working around "single-pass" constraint

I like to order my program code files as follows:

  Initial comment header

  require statements, etc.

  "main" code

  method definitions

Unfortunately, Ruby has a "single pass" execution flow
(a bit reminiscent of Pascal's single-pass compiler :-/)
that doesn't allow this order to be used, by default.

My current hack is to wrap the "main" code in a method
(e.g., main :slight_smile: and invoke it at the end of the file, I
can get around this issue. I also like the fact that it
(a) puts the code at the same level of indentation as the
code in my methods and (b) limits the scope of variables:

  #!/usr/bin/env ruby -w

···

#
  # foo - code formatting demo

  def main
    bar
  end

  def bar
    puts 'Hi!'
  end

  main

However, I have two concerns with this approach:

  * I might be missing a common Ruby idiom (at least,
     common within the small group of folks who like to
     order their code as I do).

  * I might be in danger of running into some sort of
     "dynamic language issue", in which some method has
     to be defined early, because it gets used in main's
     _definition_.

     I don't know, unfortunately, whether this is a real
     concern. Or, if it is, whether I could work around
     it by putting the location-sensitive definitions in
     front of main's definition.

Comments? Clues? Suggestions?

-r
--
http://www.cfcl.com/rdm Rich Morin
http://www.cfcl.com/rdm/resume rdm@cfcl.com
http://www.cfcl.com/rdm/weblog +1 650-873-7841

Technical editing and writing, programming, and web development

I like to order my program code files as follows:

  Initial comment header

  require statements, etc.

  "main" code

  method definitions

Unfortunately, Ruby has a "single pass" execution flow
(a bit reminiscent of Pascal's single-pass compiler :-/)
that doesn't allow this order to be used, by default.

My current hack is to wrap the "main" code in a method
(e.g., main :slight_smile: and invoke it at the end of the file, I
can get around this issue. I also like the fact that it
(a) puts the code at the same level of indentation as the
code in my methods and (b) limits the scope of variables:

  #!/usr/bin/env ruby -w
  #
  # foo - code formatting demo

  def main
    bar
  end

  def bar
    puts 'Hi!'
  end

  main

However, I have two concerns with this approach:

  * I might be missing a common Ruby idiom (at least,
     common within the small group of folks who like to
     order their code as I do).

As I don't belong to that group I don't have any insight there. :slight_smile:

Personally I don't mind having the order Ruby imposes.

  * I might be in danger of running into some sort of
     "dynamic language issue", in which some method has
     to be defined early, because it gets used in main's
     _definition_.

     I don't know, unfortunately, whether this is a real
     concern. Or, if it is, whether I could work around
     it by putting the location-sensitive definitions in
     front of main's definition.

This is not an issue at all:

16:34:42 [~]: ruby -e 'def main() foo() end; def foo() puts "icks" end; main()'
icks

IOW, the method needs to be there when it's called - not earlier.

Kind regards

  robert

···

On 21.08.2006 16:29, Rich Morin wrote:

I like to order my program code files as follows:

Initial comment header

   require statements, etc.

   "main" code

   BEGIN{
     method definitions
   }

note that there are also END{} blocks

(e.g., main :slight_smile: and invoke it at the end of the file, I
can get around this issue. I also like the fact that it
(a) puts the code at the same level of indentation as the
code in my methods and (b) limits the scope of variables:

#!/usr/bin/env ruby -w
#
# foo - code formatting demo

def main
   bar
end

def bar
   puts 'Hi!'
end

main

if you take tis to the next step it's really useful

   class Main
     def foo
     end
     def bar
     end
     def run
       foo and bar
     end
   end

   Main.new(ENV, ARGV).run if $0 == __FILE__

the reason is that it allows your program to be used as a library without
polluting the global namespace.

regards.

-a

···

On Mon, 21 Aug 2006, Rich Morin wrote:
--
to foster inner awareness, introspection, and reasoning is more efficient than
meditation and prayer.
- h.h. the 14th dali lama

I agree, but the OP wants to see the main algorithm at the top of the
file (at least, I think that's the idea), so "run" should be at the
top:
class Main
  def run
    foo and bar
  end
  def foo
  end
  def bar
  end
end

Main.new(ENV, ARGV).run if $0 == __FILE__

Neat and Tidy.. Tidy and Neat (
http://pages.eidosnet.co.uk/pobotrol/whomessy.htm )

···

On 8/22/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

if you take tis to the next step it's really useful

   class Main
     def foo
     end
     def bar
     end
     def run
       foo and bar
     end
   end

   Main.new(ENV, ARGV).run if $0 == __FILE__

the reason is that it allows your program to be used as a library without
polluting the global namespace.

--
Daniel Baird
http://tiddlyspot.com (free, effortless TiddlyWiki hosting)
http://danielbaird.com (TiddlyW;nks! :: Whiteboard Koala :: Blog ::
Things That Suck)

Assuming that my code contains generally useful functions,
this makes sense (and why bet the other way? :-). However,
I'm curious whether I need to worry about the possibility
of bringing in multiple "Main" classes and "run" methods,
if I use this approach a lot. Do you have any relevant
experience to offer?

-r

···

At 11:52 PM +0900 8/21/06, ara.t.howard@noaa.gov wrote:

   Main.new(ENV, ARGV).run if $0 == __FILE__

the reason is that it allows your program to be used as a
library without polluting the global namespace.

--
http://www.cfcl.com/rdm Rich Morin
http://www.cfcl.com/rdm/resume rdm@cfcl.com
http://www.cfcl.com/rdm/weblog +1 650-873-7841

Technical editing and writing, programming, and web development

Dont name then Main, name them somethign useful, then it won't matter how
many there are.

j`ey
http://www.eachmapinject.com

···

On 8/22/06, Rich Morin <rdm@cfcl.com> wrote:

At 11:52 PM +0900 8/21/06, ara.t.howard@noaa.gov wrote:
> Main.new(ENV, ARGV).run if $0 == __FILE__
>
> the reason is that it allows your program to be used as a
> library without polluting the global namespace.

Assuming that my code contains generally useful functions,
this makes sense (and why bet the other way? :-). However,
I'm curious whether I need to worry about the possibility
of bringing in multiple "Main" classes and "run" methods,
if I use this approach a lot. Do you have any relevant
experience to offer?

-r
--
http://www.cfcl.com/rdm Rich Morin
http://www.cfcl.com/rdm/resume rdm@cfcl.com
http://www.cfcl.com/rdm/weblog +1 650-873-7841

Technical editing and writing, programming, and web development