Why does this use a block

So I’m new to Ruby and I’m trying to use OptionParser to parse in some
command line arguments. I looked at some documentation on OptionParser
and
there is something that’s confusing me to no end. In all the examples a
block is being passed in to the constructor of the OptionParser object.
The
constructor simply makes a yield call, passing self as an argument.

What is the point of this? Can we not convert

opts = OptionParser.new() {|opts| body}

To

opts = OptionParser.new()
body

? This seems more natural to me. But the former seems like a common Ruby
idiom so I’m wondering what I am missing.

Thanks,

Jaimrk

On Oct 11, 2007, at 24:12 , Anonymous wrote:

To

opts = OptionParser.new()
body

? This seems more natural to me. But the former seems like a common
Ruby idiom so I’m wondering what I am missing.

It works both ways. Blocks are pretty, so people use them.

About using blocks in constructors in general…

(Although “initialize” is an initializer and not a constructor.
It only takes care of one part of the construction.)

“initialize” should take care of the initialization of the
object: Setting instance variables and checking whether the
instance variables are set correctly. It’s the latter which is
important.

Setting instance variables is traditionally done in two ways: a
list of arguments and a hash of options. (Or a combination of
them.) You might want to call them “arguments” and “named
arguments”.

The list:

def initialize(first_name, last_name)
@first_name = first_name.to_s
@last_name = last_name.to_s

raise ArgumentError, “first name isn’t set” unless @first_name
raise ArgumentError, “last name isn’t set” unless @last_name
end

The hash:

def initialize(options={})
@case_sensitive = options[:case_sensitive] || true
@direction = options[:direction] || :forward

raise ArgumentError, “” unless @first_name
end

In Java, you’ll often see a third way (Java style, Ruby code):

attr_writer :first_name
attr_writer :last_name

def initialize
end

something = Something.new
something.first_name = “Erik”
something.last_name = “Veenstra”

Personally, I think this is conceptually unacceptable: There’s
no way for the constructor to check whether the instance
variables are set, or whether they are set correctly.

This can be overcome by calling the initializer with a block:

attr_writer :first_name
attr_writer :last_name

def initialize(&block)
block.call(self)

raise ArgumentError, “first name isn’t set” unless @first_name
raise ArgumentError, “last name isn’t set” unless @last_name
end

Which is called like this:

Something.new do |something|
something.first_name = “Erik”
something.last_name = “Veenstra”
end

Personally, I always try to freeze the object once it is
created: (This has advantages beyond the scope of this writing.)

attr_writer :first_name
attr_writer :last_name

def initialize(&block)
block.call(self)

raise ArgumentError, “first name isn’t set” unless @first_name
raise ArgumentError, “last name isn’t set” unless @last_name

freeze
end

There’s some more advantages. For example, the object can often
be collected earlier. Consider this example, in the main of the
application:

direction = :forward

EV::CommandLine.new do |cl|
cl.option(“-r”, “–reverse”) {direction = :backward}
end.parse(ARGV)

…instead of…

direction = :forward
cl = EV::CommandLine.new
cl.option(“-r”, “–reverse”) {direction = :backward}
cl.parse(ARGV)

When will cl be collected, in the second piece of code? Never?

It’s just my opinion. Feel free to ignore me…

gegroet,
Erik V. - http://www.erikveen.dds.nl/

2007/10/11, Eric H. [email protected]:

opts = OptionParser.new() {|opts| body}

To

opts = OptionParser.new()
body

? This seems more natural to me. But the former seems like a common
Ruby idiom so I’m wondering what I am missing.

It works both ways. Blocks are pretty, so people use them.

There are in fact important differences to both approaches. First,
OptionParser’s #initialize is free to yield whatever it decides to the
block. So you are not guaranteed to receive the new OptionParser
instance. This is important to keep in mind because the
implementation might change at a later point so the lib could yield a
different instance which should, of course, support the documented
interface.

Second, with the block form OptionParser#initialize is able to detect
when the user initialization has finished and can do finalizing work.
It could, for example, invoke #freeze to make sure the configuration
is not changed any more. Or it can verify that client code properly
initialized it (avoiding duplicate or ambiguous option settings for
example).

An alternative that some may find nicer would implement OptionParser()
(a method) in Kernel and have that receive the block.

Kind regards

robert

Anonymous wrote:

To

opts = OptionParser.new()
body

? This seems more natural to me. But the former seems like a common Ruby
idiom so I’m wondering what I am missing.

You might want to use the shortcut

option_parser = OptionParser.new do |o|
o.foo = “foo”
o.bar = “bar”

end

during initialization of the object instead of using the long name, that
will be used later in the program after you forgot, what “o” meant.

I don’t know if this is the case with OptionParser, but many methods
also want to do some housekeeping after the execution of the block, for
example, open(…) do |f| … end closes the opened file. A constructor
might want to check his configuration (given in the block) and raise an
exception, if errors were found. This is better than creating a wrongly
configured object, that only will throw an exception later in the
program.

On 10/11/07, Anonymous [email protected] wrote:

To

opts = OptionParser.new()
body

? This seems more natural to me. But the former seems like a common Ruby
idiom so I’m wondering what I am missing.

Thanks,

Jaimrk

You are asking a bunch of questions here, but I’ll try my hand at one of
them.

yield self

It pretty much does exactly what the statement says it does. Why
would you do this upon initializing an object? I suppose, because you
might want something else to accomplish something during
initialization.

Blocks also give you control of scope and give the programmer a sense
of finalization. File#open for example.

Todd

Anonymous wrote:

So I’m new to Ruby and I’m trying to use OptionParser to parse in some
command line arguments.

In ruby, a lot of methods can be called with or without a block. When a
method is called with a block, it may do some extra stuff. I think what
the other posters are saying is that the initialize() method in
OptionParser, which is called when you call new(), may be defined to do
some extra things when it’s called with a block.

Here’s an example of a method doing some extra things when it’s called
with a block:

class Dog
def age
@age
end

def age=(num)
@age = num
end

def initialize
if block_given?
yield self

  if @age == nil
    puts "You must set the dog's age."
  elsif @age > 20
    puts "Error.  That dog is dead."
  elsif @age < 0
    puts "Error.  That dog isn't born yet."
  end

end

end
end

d = Dog.new
d.age = -3
puts “That dog’s age is #{d.age}.”
d.age = 22
puts “That dog’s age is #{d.age}.”

d = Dog.new do |dog|
dog.age = 22
end

–output:–
That dog’s age is -3.
That dog’s age is 22.
Error. That dog is dead.

On Oct 11, 5:27 am, Erik V. [email protected] wrote:

Personally, I always try to freeze the object once it is
created: (This has advantages beyond the scope of this writing.)

So, most of your objects are immutable?

On 10/11/07, Robert K. [email protected] wrote:

2007/10/11, Eric H. [email protected]:

On Oct 11, 2007, at 24:12 , Anonymous wrote:

So I’m new to Ruby and I’m trying to use OptionParser to parse in some
command line arguments. I looked at some documentation on
OptionParser and there is something that’s confusing me to no end.
In all the examples a block is being passed in to the constructor
of the OptionParser object.

Second, with the block form OptionParser#initialize is able to detect
when the user initialization has finished and can do finalizing work.
It could, for example, invoke #freeze to make sure the configuration
is not changed any more. Or it can verify that client code properly
initialized it (avoiding duplicate or ambiguous option settings for
example).

I’m pretty sure that I’ve seen a variant on this in which initialize
evaluates the block with instance_eval rather than yield or call.
This allows the block to invoke private methods during initialization.

IIRC the Ruby tk bindings so this.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Oct 11, 3:33 pm, Erik V. [email protected] wrote:

So, most of your objects are immutable?

Yes. (If possible…)

Q: Why?
A:Functional Relational Programming: Out of the tar pit | Lambda the Ultimate

Have you thought of programming in Haskell? :wink:

I’m familiar with some of the benefits of avoiding state with respect
to functional programming languages, but to impose that strictly on
Ruby seems to be working against the grain. I do code many functions
(i.e. not associated with a meaningful instance) in a functional style
w/o side effects, but when working with objects, having methods modify
the state of objects seems to be very natural and productive in Ruby.

I’m curious though because of my recent research into Haskell, SML,
etc… Do you have an example of this style of programming (frozen
objects) in Ruby that you feel is compelling?

Brian A.

2007/10/11, Brian A. [email protected]:

On Oct 11, 3:33 pm, Erik V. [email protected] wrote:

So, most of your objects are immutable?

Yes. (If possible…)

Q: Why?
A:Functional Relational Programming: Out of the tar pit | Lambda the Ultimate

Have you thought of programming in Haskell? :wink:

:slight_smile:

I’m familiar with some of the benefits of avoiding state with respect
to functional programming languages, but to impose that strictly on
Ruby seems to be working against the grain. I do code many functions
(i.e. not associated with a meaningful instance) in a functional style
w/o side effects, but when working with objects, having methods modify
the state of objects seems to be very natural and productive in Ruby.

Actually programming completely without side effects defies the core
of the OO paradigm. Objects simply do not make much sense if methods
cannot produce side effects.

I’m curious though because of my recent research into Haskell, SML,
etc… Do you have an example of this style of programming (frozen
objects) in Ruby that you feel is compelling?

Look at all the math in Ruby - I believe it makes very much sense the
way it is done today. But any collection type would be rather
inefficient when you always had to create a new object for every
change - at least in the Ruby world. I believe that some functional
language runtime systems are pretty smart and can optimize this to a
certain extend.

It’s all about balance. Use side effects when appropriate, use
immutables when appropriate.

Kind regards

robert

So, most of your objects are immutable?

Yes. (If possible…)

Q: Why?
A: Functional Relational Programming: Out of the tar pit | Lambda the Ultimate

gegroet,
Erik V. - http://www.erikveen.dds.nl/

On 10/12/07, Robert K. [email protected] wrote:

Actually programming completely without side effects defies the core
of the OO paradigm. Objects simply do not make much sense if methods
cannot produce side effects.

I’d agree. Multi-paradigm programming is one thing, but this seems
more like counter paradigm programming.

Sort of like speaking English fluent with grammar French.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/