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

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

···

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. 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.

--
Poor workers blame their tools. Good workers build better tools. The
best workers get their tools to do the work for them. -- Syndicate Wars

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/

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. 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.
  

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.

···

--
Florian Frank

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

···

On 10/11/07, Anonymous <jaimrk@aol.com> 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. 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

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.

···

--
Posted via http://www.ruby-forum.com/\.

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

···

2007/10/11, Eric Hodel <drbrain@segment7.net>:

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. 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.

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

So, most of your objects are immutable?

···

On Oct 11, 5:27 am, Erik Veenstra <erikv...@gmail.com> wrote:

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

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.

···

On 10/11/07, Robert Klemme <shortcutter@googlemail.com> wrote:

2007/10/11, Eric Hodel <drbrain@segment7.net>:
> 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.

> 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).

--
Rick DeNatale

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

So, most of your objects are immutable?

Yes. (If possible...)

Q: Why?

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

···

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 Adkins

···

On Oct 11, 3:33 pm, Erik Veenstra <erikv...@gmail.com> 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

--
http://www.lojic.com

> > So, most of your objects are immutable?
>
> Yes. (If possible...)
>
> Q: Why?
> A:http://lambda-the-ultimate.org/node/1446

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

···

2007/10/11, Brian Adkins <lojicdotcom@gmail.com>:

On Oct 11, 3:33 pm, Erik Veenstra <erikv...@gmail.com> wrote:

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.

···

On 10/12/07, Robert Klemme <shortcutter@googlemail.com> 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.

--
Rick DeNatale

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