Consider the following contrived examples:
def func1()
ret = []
t = nil
5.times do |i|
t = yield i
ret << t
end
ret
end
func1 { |b| b + 10 } # [ 10, 11, 12, 13, 14 ]
def func2(&block)
ret = []
t = nil
5.times do |i|
t = block.call(i)
ret << t
end
ret
end
func2 { |b| b + 10 } # [ 10, 11, 12, 13, 14 ]
Is this just TMTOWTDI, or is there a difference?
Dan
···
–
/^Dan Debertin$/
airboss@nodewarrior.org
www.nodewarrior.org
ignorami: n:
The art of folding problem users into representational shapes.
Consider the following contrived examples:
But I hate contrived examples!
def func1()
ret =
t = nil
5.times do |i|
t = yield i
ret << t
end
ret
end
func1 { |b| b + 10 } # [ 10, 11, 12, 13, 14 ]
def func2(&block)
ret =
t = nil
5.times do |i|
t = block.call(i)
ret << t
end
ret
end
func2 { |b| b + 10 } # [ 10, 11, 12, 13, 14 ]
Is this just TMTOWTDI, or is there a difference?
AFAIK, TMTOWTDI.
GS
···
----- Original Message -----
From: “Dan Debertin” airboss@nodewarrior.org
Dan
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…
require "benchmark"
include Benchmark
N = 500000
def block(&b)
N.times { b.call(1) }
end
def no_block
N.times { yield 1 }
end
bm(10) do |test|
test.report("block") { block {|i|} }
test.report("no block") { no_block {|i|} }
test.report("block") { block {|i|} }
test.report("no block") { no_block {|i|} }
end
dave[~/tmp 22:58:57] ruby t.rb
user system total real
block 3.430000 0.000000 3.430000 ( 3.450126)
no block 1.320000 0.000000 1.320000 ( 1.383497)
block 3.450000 0.000000 3.450000 ( 3.450232)
no block 1.330000 0.000000 1.330000 ( 1.329939)
Yup - there’s a difference 
Cheers
Dave
The parameter passing is also different, quoting Matz (from ruby-talk
46413):
First, you have to learn several tips:
(a) block parameter |v| means takes everything in a single variable,
which is better described as |*v|.
(b) “call” requires exact number of required argument, whereas
“yield” fills nil for fewer arguments and ignores too much
arguments.
HTH,
– Shanko
“Dan Debertin” airboss@nodewarrior.org wrote in message
news:87ptwitcpq.wl@discus.nodewarrior.org…
···
Consider the following contrived examples:
def func1()
ret =
t = nil
5.times do |i|
t = yield i
ret << t
end
ret
end
func1 { |b| b + 10 } # [ 10, 11, 12, 13, 14 ]
def func2(&block)
ret =
t = nil
5.times do |i|
t = block.call(i)
ret << t
end
ret
end
func2 { |b| b + 10 } # [ 10, 11, 12, 13, 14 ]
Is this just TMTOWTDI, or is there a difference?
Dan
/^Dan Debertin$/
airboss@nodewarrior.org
www.nodewarrior.org
ignorami: n:
The art of folding problem users into representational shapes.
“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| ii + 3iii } }
x.report(“each_block”) { stack.each_block {|i| ii + 3iii } }
x.report(“each_yield”) { stack.each_yield {|i| ii + 3iii } }
}
$ 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
"Christoph"wrote
def push(data)
@data = data
@rest = clone
end
Sigh, …
def push(data)
@rest = clone
@data = data
end
/Christoph