Two kind of closures?...

C

Csaba Henk

The post

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/47474

tells us that one difference between

def foo
...
yield
...
end

and

def foo(&b)
...
b[...]
...
end

is performance, as "'yield' does not create a proc object, while (&block)
does." (The other is the way arguments are passed to the block, but it's not
important here.)

When I've been reading that post, my first thought was that in the "yield"
case a syntactic object (parse tree of the block) is passed internally
(similarly as in the following scheme example:

(define (foo blk) (eval blk))
(foo '(display "today is almost tomorrow"))

), but no, it can't be so, as the bindings of the block are passed when you
use yield as well (

x=8
def foo
yield
end
foo {x}
=> 8

), so both in the "&b" and in the "yield" cases, a closure is created. The
common sense suggests that closures are simply procedure objects, but here
it's not not as simple: as the benchmark in the above cited post shows,
there is a performance difference between the two solutions.

So what I can imply there are two kind of closures in ruby: proc objects and
lightweight closures used with yield. Now I wonder, what's the difference,
what is the addon that is provided with a proc object but is missing in case
of the "lightweight closures"?

Thanks,
--
Csaba

"There's more to life, than books, you know but not much more..."
[The Smiths]
***
If you want to send me a mail, see it in the mailto link at
http://www.renyi.hu/~ekho/egyelore.html
 
T

ts

C> lightweight closures used with yield. Now I wonder, what's the difference,
C> what is the addon that is provided with a proc object but is missing in case
C> of the "lightweight closures"?

svg% cat b.rb
#!/usr/bin/ruby
class Proc
alias old_call call
def call(*args)
puts "new Proc#call"
old_call(*args)
end
end

def tt(&b)
puts "==> Proc#call"
b.call
puts "==> yield"
yield
end

tt { p 12 }
svg%

svg% b.rb
==> Proc#call
new Proc#call
12
==> yield
12
svg%


Guy Decoux
 
R

Robert Klemme

So what I can imply there are two kind of closures in ruby: proc objects and
lightweight closures used with yield. Now I wonder, what's the difference,
what is the addon that is provided with a proc object but is missing in case
of the "lightweight closures"?

Just a wild guess: the difference might be that the Proc adds a Ruby object
to the closure. So internally a Proc might use what you call "lightweigt
closure", but it has the overhead that comes with object creation (namely
memory allocation, registration with the GC and maybe initialization).
"There's more to life, than books, you know but not much more..."
[The Smiths]

:)

Kind regards

robert
 
J

Joel VanderWerf

Csaba Henk wrote:
...
So what I can imply there are two kind of closures in ruby: proc objects and
lightweight closures used with yield. Now I wonder, what's the difference,
what is the addon that is provided with a proc object but is missing in case
of the "lightweight closures"?

One reason to create a Proc instead of just yielding is that the Proc
can be saved away somewhere and called later, after the scope of the
block is gone:

def defer(&bl)
@later_stuff = bl
end

def handle_deferred
@later_stuff.call
end

defer do
puts "hello"
end

handle_deferred
 

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,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top