On Sunday 23 November 2003 02:24 am, Tanaka Akira wrote:
> In article <200311221024.05642.transami / runbox.com>,
>
>   "T. Onoma" <transami / runbox.com> writes:
> > opts = OpenUriOptions.new
> > def opts.progress_bar( percent_done )
> >   puts "Yeah, we're at " + percent_done + "% now!"
> > end
> > open( "http://whytheluckystiff.net/why.yml", opts )
>
> I can't see any benefits over non-singleton method version:

It's actually kind of mind boggling just how nearly identical these two code 
snippets are.

  opts = OpenUriOptions.new
  opts.progress_bar do |percent_done|
    puts "Yeah, we're at " + percent_done + "% now!"
  end
  open( "http://whytheluckystiff.net/why.yml", opts )

  opts = OpenUriOptions.new
  def opts.progress_bar( percent_done )
?   puts "Yeah, we're at " + percent_done + "% now!"
  end
  open( "http://whytheluckystiff.net/why.yml", opts )

If fact the distinction is wholly in the 2nd line where the do moves over to 
def and the | | become ( ). That's it!

And of course the end result is exactly the same. So...

> Why singleton?

There's something compelling about them in conjunction with Duck Typing. But 
it has less to do with the front-end, as show here, and more to do with with 
the implementation code that underlys these two examples. The distinction is 
one of specific/active verses general/passive programming.

The first example requires that the implementation be more active and 
specific, taking care of all the assignments to the opts with built in 
methods.

  class OpenUriOptions
    attr_reader :progress_block
    def progress_bar( &progress_block )
      @progress_block = progress_block
    end
  end
  ...
  def open(name, opts, &block)
    ...
     opts.progress_block.call(t) if opts.progress_block
    ...
  end

The second is passive and general, and needs do nothing special to gain new 
functionality except to ask if it has been given it.

  class OpenUriOptions
  end
  ...
  def open(name, opts, &block)
    ...
     opts.progress_block(t) if opts.respond_to?(:progress_block)
    ...
  end

So the advantage is having less implementation code. In fact you could write a 
whole class that had nearly zero assignment code and all respond_to? 
activators. (That would be interseting to see actually.) On the downsie it 
might have some small performance loss, and, of course, we're simply not used 
to the idea. 

Perhaps you see it differently, but for me, not only does it seem odd, but it 
feels new and exciting at the same time. But hey, I'm a wild and crazy kind 
of guy.

-t0