What Does Ruby's Begin Do

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 yielded 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 a begin/end block, or a code block, adding somewhat to the confusion
  • do...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



Leave a reply



Submit