What does Ruby's BEGIN do?
BEGIN
and END
set up blocks that are called before anything else gets executed, or after everything else, just before the interpreter quits.
For instance, running this:
END { puts 'END block' }
puts 'foobar'
BEGIN { puts 'BEGIN block' }
Outputs:
BEGIN block
foobar
END block
Normally we'd use a bit more logical order for the BEGIN
and END
blocks, but that demonstrates what they do.
What are the reserved words BEGIN or END used for in Ruby?
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.
What is use of ||= begin....end block in Ruby?
First of all, you need to be aware that a defined method inherently includes the functionality of a begin ... end
block.
In the context of exception handling, def method_name ... end
is functionally equivalent to begin ... end
. Both can include rescue
statements for example.
The two blocks of code you have shared are actually identical, and there is no benefit in one over the other ... unless your method
is needed in more than one place. In that case, you DRY up your code by putting the logic into a single method and calling it from multiple other places.
What is the purpose of using ruby begin without rescue?
This example is just bad - for the described case, there is no difference in behavior (and the bytecode will look very similar if not the same).
begin ... end
block can be used for grouping several expressions - for example, for memoizing the intermediate result of some heavy calculations without additional intermediate assignments, like
some_var = begin
# a bunch of expressions goes there
end
# continue calculations using some_var
Actually, begin ... end
block acts in pretty much the same way as def ... end
does to define a method. And because of this similarity begin .... end
is not used very often in the production code - in most practical cases it's better to move the group of closely related expressions into a separate method.
There is one case when this block can make the difference - consider
some_method while false
vs
begin
some_method
end while false
In the former snippet some_method
isn't called at all, while in the latter it will be called once. But this usage is kind of discouraged - it makes the code trickier (the same can be done in a much more readable way with loop
and explicit break
)
What does ||= do in Ruby
This will assign bar
to foo
if (and only if) foo
is nil
or false
.
EDIT: or false, thanks @mopoke.
Are there unintended consequences of Ruby's `begin ... end` without `rescue` used as a code block?
I use this sometimes if I want to assign something to a variable but I have to calculate the value I want to assign first. It makes the code a little bit more tidy this way. I think it's user preference. Basically you are saying: I am assigning something to foo, but in order to get the value I want I first need to do some things. It's particularly useful when doing memoization, so instead of
if @cache.nil?
do_something!
@cache = read_value
end
You can do
@cache ||= begin
do_something!
read_value
end
What you are taking advantage here is that the Ruby interpreter has a stack, and each expression will usually push something on the stack, or take something from the stack. Assignment just takes the last thing from the stack and assigns it (in this case the last line from begin/end). Many times knowing this (stack approach in Ruby) can be useful.
I don't think it violates least surprise though, I think it's user preference wheather you want to use it or not.
You can see that it doesn't do anything unexpected by looking at what bytecode instructions it generates in Ruby MRI 1.9:
RubyVM::InstructionSequence::compile("c = begin; a = 5; 6; end").to_a
[:trace, 1],
[:trace, 1],
[:putobject, 5],
[:setlocal, 2],
[:trace, 1],
[:putobject, 6],
[:dup],
[:setlocal, 3],
[:leave]
Trace is just for stack traces, you can ignore that. Dup duplicates the last item on the stack. In this example the number of the local variable a
is 2
and the number of the local variable c
is 3
(hence putobject, 2
will assign to variable a
, etc).
The only side-effect of this compared to a = 5; c = 6
is the dup
instruction, which means the stack size of your method will be larger by 1 slot. But this is not particularly important because it only has any effect while the interpreter is inside this particular method, and memory for stack is pre-reserved anyway, so it only means the stack pointer will be decremented by 1 more than it would otherwise. So basically no change at all. With optimizations turned on even the dup
will probably disappear.
Begin, Rescue and Ensure in Ruby?
Yes, ensure
ensures that the code is always evaluated. That's why it's called ensure
. So, it is equivalent to Java's and C#'s finally
.
The general flow of begin
/rescue
/else
/ensure
/end
looks like this:
begin
# something which might raise an exception
rescue SomeExceptionClass => some_variable
# code that deals with some exception
rescue SomeOtherException => some_other_variable
# code that deals with some other exception
else
# code that runs only if *no* exception was raised
ensure
# ensure that this code always runs, no matter what
# does not change the final value of the block
end
You can leave out rescue
, ensure
or else
. You can also leave out the variables in which case you won't be able to inspect the exception in your exception handling code. (Well, you can always use the global exception variable to access the last exception that was raised, but that's a little bit hacky.) And you can leave out the exception class, in which case all exceptions that inherit from StandardError
will be caught. (Please note that this does not mean that all exceptions are caught, because there are exceptions which are instances of Exception
but not StandardError
. Mostly very severe exceptions that compromise the integrity of the program such as SystemStackError
, NoMemoryError
, SecurityError
, NotImplementedError
, LoadError
, SyntaxError
, ScriptError
, Interrupt
, SignalException
or SystemExit
.)
Some blocks form implicit exception blocks. For example, method definitions are implicitly also exception blocks, so instead of writing
def foo
begin
# ...
rescue
# ...
end
end
you write just
def foo
# ...
rescue
# ...
end
or
def foo
# ...
ensure
# ...
end
The same applies to class
definitions and module
definitions.
However, in the specific case you are asking about, there is actually a much better idiom. In general, when you work with some resource which you need to clean up at the end, you do that by passing a block to a method which does all the cleanup for you. It's similar to a using
block in C#, except that Ruby is actually powerful enough that you don't have to wait for the high priests of Microsoft to come down from the mountain and graciously change their compiler for you. In Ruby, you can just implement it yourself:
# This is what you want to do:
File.open('myFile.txt', 'w') do |file|
file.puts content
end
# And this is how you might implement it:
def File.open(filename, mode='r', perm=nil, opt=nil)
yield filehandle = new(filename, mode, perm, opt)
ensure
filehandle&.close
end
And what do you know: this is already available in the core library as File.open
. But it is a general pattern that you can use in your own code as well, for implementing any kind of resource cleanup (à la using
in C#) or transactions or whatever else you might think of.
The only case where this doesn't work, if acquiring and releasing the resource are distributed over different parts of the program. But if it is localized, as in your example, then you can easily use these resource blocks.
BTW: in modern C#, using
is actually superfluous, because you can implement Ruby-style resource blocks yourself:
class File
{
static T open<T>(string filename, string mode, Func<File, T> block)
{
var handle = new File(filename, mode);
try
{
return block(handle);
}
finally
{
handle.Dispose();
}
}
}
// Usage:
File.open("myFile.txt", "w", (file) =>
{
file.WriteLine(contents);
});
Does begin . . . end while denote a 'block'?
Block has a special meaning in Ruby. According to Matz, Ruby's creator, you can look at a block as a nameless function - typically something that can be yield
ed into, and which may also take parameters.
You may see the following kind of disamiguation when describing Ruby syntax:
begin
...end
(what is called block in other languages) may sometimes be referred to simply as what it is, i.e. an expression (which may in turn contain other expressions - an expression is simply something that has a return value) in Ruby. Some references will still call it abegin/end block
, or acode block
, adding somewhat to the confusiondo
...end
or{...}
will always be referred to as a block in Ruby
For examples, peruse the the Ruby syntax man page, e.g.
begin
expression
end
expression
while
expression
loop
block
For further reading, see:
- Programming Ruby
- Ruby (from other languages)
- Much, much more documentation
What inspired Ruby's =begin .. =end comment block syntax?
yes, this is Perl
Perl uses
=begin
This is a comment line
it explains that the next line of code displays
a welcome message
=cut
have a look here: http://en.wikipedia.org/wiki/Comparison_of_programming_languages_(syntax)#Comments
Related Topics
How to Ensure a Rake Task Only Running a Process at a Time
How to Build Task 'Gems:Install'
How to Find Out the Starting Point for Each Match in Ruby
Rake: Logging Any Task Executing
Naming Conventions for Boolean Attributes
What's Gem Can Operate Excel on Linux
Vim Syntax Highlighting for Ruby 1.9
How to Set Ruby Environment in Linux
How to Connect to a Mongodb from Ruby Code
How to Do Complex Querying with Logical Operations by Using Searchkick
Is Communication Between Two Ruby Processes Possible/Easy
Ruby - No Pid Found in Tmp/Pids/Thin.Pid (Thin::Pidfilenotfound)