Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the reserved words BEGIN or END used for in Ruby?

Tags:

This is a very hard to find word because in most cases they are not sensitive during a search. The best I could find outside of documentation is a test in IRB.

 BEGIN{puts x = 10}  10 
like image 948
Douglas G. Allen Avatar asked Mar 10 '13 18:03

Douglas G. Allen


2 Answers

As all keywords BEGIN and END are documented as public instance methods of Object (even though you won't see them returned from Object.public_instance_methods)

BEGIN Designates, via code block, code to be executed unconditionally before sequential execution of the program begins. Sometimes used to simulate forward references to methods.

puts times_3(gets.to_i)  BEGIN {   def times_3(n)     n * 3   end } 

END Designates, via code block, code to be executed just prior to program termination.

END {    puts "Bye!"  } 

Some more detailed explanation from Programming Ruby The Pragmatic Programmer's Guide

BEGIN and END Blocks

Every Ruby source file can declare blocks of code to be run as the file is being loaded (the BEGIN blocks) and after the program has finished executing (the END blocks).

BEGIN {      begin code  }  END {   end code  } 

A program may include multiple BEGIN and END blocks. BEGIN blocks are executed in the order they are encountered. END blocks are executed in reverse order.

like image 78
Mchl Avatar answered Sep 24 '22 16:09

Mchl


One thing that hasn't been mentioned is that in earlier versions of Ruby, BEGIN was unconditional:

if false   BEGIN { puts "Up is down, hot is cold, good is evil!" } end 

If you try that with Ruby 1.8.7, the sentence is printed, even though it's in the branch of if that isn't taken.

Under Ruby 2.0.0, it's a syntax error to use BEGIN outside of the top-level (a much smarter way to handle that):

unconditional.rb:2: BEGIN is permitted only at toplevel   BEGIN { puts "Up is down, hot is cold, good is evil!" }        ^ 

Edit: In a way, nobody has answered the question you raise in your comment: Why does Ruby have BEGIN at all? I'll try. BEGIN comes to Ruby (like many things) from Perl. Perl has it because it existed in awk. It made a ton of sense in awk because by default, an awk file consists of a series of patterns and actions:

/foo/ { print $1 } /bar/ { print $2 } 

Every pattern is checked for every line. If the pattern matches, then the action is performed. Otherwise, awk moves on to the next pattern. So in the mini script above, if the line matches 'foo', then the first field is printed. If the line matches 'bar', then the second field is printed.

But by now you can see the gap that BEGIN (and END) blocks fill: What if you want to do something unconditionally before any intput has been tested or after all the input has been seen (like print a header at the top of your report or print a row of totals at the end of the report)? Normal awk lines of pattern + action can't help you there.

That's why BEGIN and END exist. But I'm not sure how useful they are for modern, idiomatic Ruby scripts. But as dbenhur points out in the comments, you can still use Ruby very well for awk-like one-liners. (I also have a recollection that MiniTest, the standard Ruby testing library, used to use an at_exit function for testing, but I'm not sure it does any longer.)

Two good links about Ruby, awk and Ruby one-liners:

  • AWK-ward Ruby by Ryan Tomayko
  • Ruby one-liners
like image 21
Telemachus Avatar answered Sep 22 '22 16:09

Telemachus