Sweet Lord!

  • Thread starter Daniel Schierbeck
  • Start date
D

Daniel Schierbeck

Why haven't I thought of this before?

class Terminal
include Enumerable

def each(&block)
while input = gets
block.call(input.chomp)
end
end
end

terminal = Terminal.new

# terminate the loop with ctrl-d, or whatever works for you.
terminal.entries
terminal.map{|line| line.to_sym}
terminal.inject(""){|str, line| str << line}



Yet another epiphany. Thank you, Ruby.


Cheers,
Daniel
 
W

William James

Daniel said:
Why haven't I thought of this before?

class Terminal
include Enumerable

def each(&block)
while input = gets
block.call(input.chomp)
end
end

def each
while input = gets
yield input.chomp
end
end
 
P

Phil Tomson

def each
while input = gets
yield input.chomp
end
end

Equivilent code, actually. It's a case of "you say tomaTOE I say tomAHto"
Personally, I tend to prefer the 'block.call' because you explicitly
say you're passing in a block in the definition of the method, so if
someone is reading your code they can easily tell that the method
takes a block. In the case of yield you might need to read through a
good bit of code before you find out that the method takes a block.


Phil
 
M

Marcin Mielżyński

Phil said:
Equivilent code, actually. It's a case of "you say tomaTOE I say tomAHto"
Personally, I tend to prefer the 'block.call' because you explicitly
say you're passing in a block in the definition of the method, so if
someone is reading your code they can easily tell that the method
takes a block. In the case of yield you might need to read through a
good bit of code before you find out that the method takes a block.


Phil

block.call is significantly slower since conversion from block to Proc
object involves copying references of a closure to Proc instance.

lopex
 
D

Daniel Schierbeck

Phil said:
Equivilent code, actually. It's a case of "you say tomaTOE I say tomAHto"

Actually, the `yield' version is significantly faster. When using the
`&block' syntax, a Proc object is created for each iteration. From what
I've gathered, that doesn't happen when using `yield'.


Cheers,
Daniel
 
D

dblack

Hi --

Equivilent code, actually. It's a case of "you say tomaTOE I say tomAHto"
Personally, I tend to prefer the 'block.call' because you explicitly
say you're passing in a block in the definition of the method, so if
someone is reading your code they can easily tell that the method
takes a block. In the case of yield you might need to read through a
good bit of code before you find out that the method takes a block.

It does seem that yielding is faster; note the effect of turning the
block into a Proc object:

require 'benchmark'
include Benchmark

n = 100000

def y
end

def b(&block)
end

bm do |x|
x.report("call") { n.times { b { } } }
x.report("yield") { n.times { y { } } }
end

# Output:

user system total real
call 1.860000 0.040000 1.900000 ( 2.874001)
yield 0.220000 0.000000 0.220000 ( 0.249164)


David

--
"To fully realize the potential of Rails, it's crucial that you take
the time to fully understand Ruby--and with "Ruby for Rails" David
has provided just what you need to help you achieve that goal."
-- DAVID HEINEMEIER HANSSON, in the foreword to RUBY FOR RAILS.
Complete foreword & sample chapters at http://www.manning.com/black!
 
P

Phil Tomson

Hi --



It does seem that yielding is faster; note the effect of turning the
block into a Proc object:

require 'benchmark'
include Benchmark

n = 100000

def y
end

def b(&block)
end

bm do |x|
x.report("call") { n.times { b { } } }
x.report("yield") { n.times { y { } } }
end

# Output:

user system total real
call 1.860000 0.040000 1.900000 ( 2.874001)
yield 0.220000 0.000000 0.220000 ( 0.249164)

That is a fairly significant difference, so maybe I should revise my
statement to say that the two different ways acheive the same effect
ignoring differences in runtime ;-)

Phil
 
J

Joel VanderWerf

Phil said:
takes a block. In the case of yield you might need to read through a
good bit of code before you find out that the method takes a block.

Note that rdoc can scan for yields, and document them.
 
W

William James

Daniel said:
Thanks! Yes, that's of course a whole lot faster.


Cheers,
Daniel

I didn't know that it would be faster; I only knew that using &block
is SO MUCH UGLIER!
 
D

Daniel Schierbeck

William said:
I didn't know that it would be faster; I only knew that using &block
is SO MUCH UGLIER!

That, my friend, is a matter of taste.


Cheers,
Daniel
 
M

Marcin Mielżyński

Daniel said:
That, my friend, is a matter of taste.

There is nothing without a purpose. Consider an object method that takes
a block and it doesn't want to execute it immediately. What would you do
without a &block ?


lopex
 
W

William James

Daniel said:
That, my friend, is a matter of taste.

Some have good taste. Some have very bad taste; they relish a
turd more than a chocolate bar or enjoy needlessly using &block.
 
W

William James

Marcin said:
There is nothing without a purpose. Consider an object method that takes
a block and it doesn't want to execute it immediately. What would you do
without a &block ?

Utterly illogical. That is like saying that sometimes we must amputate
a
man's foot in order to save his life, and that therefore we must always
amputate a man's foot.
 
W

why the lucky stiff

Some have good taste. Some have very bad taste; they relish a
turd more than a chocolate bar or enjoy needlessly using &block.

But, you have to admit, it does stand to reason that feces would require more
relish than a Hershey's.

_why
 
D

Daniel Schierbeck

William said:
Utterly illogical. That is like saying that sometimes we must amputate
a
man's foot in order to save his life, and that therefore we must always
amputate a man's foot.

I think he was trying to say that there are times when `yield' is the
best choice, and there are times when `&block' is. It all depends on the
situation.


Cheers,
Daniel
 
R

Robert Klemme

2006/7/8 said:
Why haven't I thought of this before?

class Terminal
include Enumerable

def each(&block)
while input = gets
block.call(input.chomp)
end
end
end

terminal = Terminal.new

# terminate the loop with ctrl-d, or whatever works for you.
terminal.entries
terminal.map{|line| line.to_sym}
terminal.inject(""){|str, line| str << line}



Yet another epiphany. Thank you, Ruby.

Is chomp really worth a new class? Note that you can do all of this
already with an IO:

$ ruby -e 'STDIN.each {|line| p line}'
dd
"dd\n"
ff
"ff\n"

$ ruby -e 'p STDIN.entries'
dd
ff
["dd\n", "ff\n"]

$ ruby -e 'p STDIN.map {|line| line.inspect}'
ddd
sss
["\"ddd\\n\"", "\"sss\\n\""]

Kind regards

robert
 
M

Marcin Mielżyński

Daniel said:
I think he was trying to say that there are times when `yield' is the
best choice, and there are times when `&block' is. It all depends on the
situation.

;D

Right.

yield is better when you invoke a block immediately, but block.call is
the _only_ way when you want to save the block for later execution.

lopex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top