"Dave Thomas" <Dave / PragmaticProgrammer.com> wrote in message
news:m2vg6anngv.fsf / zip.local.thomases.com...
> Dan Debertin <airboss / nodewarrior.org> writes:
>
> >       t = yield i
>
> >       t = block.call(i)
>
> > Is this just TMTOWTDI, or is there a difference?
>
> There's an internal difference, in that 'yield' does not create a proc
> object, while (&block) does. This might make a performance
> difference. Let's find out...

In recursive situations it's sort of advantageous to use the block
form since it prevents the creation of unnecessary blocks.
Furthermore, it's more elegant ...

---
$ cat stack.rb
class Stack
  NullStack = new

  def initialize()
    @top = self
    @rest = NullStack
  end

  def each_mixed(&b)
    yield @data
    @rest.each_mixed(&b)
  end

  def each_block(&b)
    b.call(@data)
    @rest.each_block(&b)
  end

  def each_yield
    yield @data
    @rest.each_yield {|r| yield r }
  end

  def push(data)
    @data = data
    @rest = clone
  end

  def pop()
    unless empty?
      data = @data
      @rest = @rest.rest
      data
    else
      nil
    end
  end

  def empty?; NullStack.equal?(@rest) end
  protected
  attr_reader :rest

  class << NullStack
    protected
    def each_mixed; end
    def each_block; end
    def each_yield; end
    # undef all unapplicable methods
    undef :pop
    # etc.
  end
  end

stack = Stack.new
1000.times {|i| stack.push(i) }

require 'benchmark'
Benchmark::bmbm {|x|
  x.report("each_mixed") { stack.each_mixed {|i| i*i + 3*i*i*i } }
  x.report("each_block") { stack.each_block {|i| i*i + 3*i*i*i } }
  x.report("each_yield") { stack.each_yield {|i| i*i + 3*i*i*i } }
}
---
$ ruby stack.rb
Rehearsal ----------------------------------------------
each_mixed   0.170000   0.020000   0.190000 (  0.184000)
each_block   0.080000   0.000000   0.080000 (  0.089000)
each_yield  14.761000   0.010000  14.771000 ( 15.143000)
------------------------------------ total: 15.041000sec

                 user     system      total        real
each_mixed   0.080000   0.000000   0.080000 (  0.083000)
each_block   0.080000   0.000000   0.080000 (  0.087000)
each_yield  12.929000   0.000000  12.929000 ( 13.101000)
---

/Christoph