[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

block equality

Tom Jordan

8/15/2006 9:24:00 PM

Is there a way to compare two blocks with each other?

If you promote a block into a Proc, how would you know that the
original block was the same?

This is what I want to do

(1..10).each do
once { puts "Hi Tom"}
end

I've tried to implement once like this

class << self
def once(&block)
@ids ||= {}
block.call unless @ids.key? block.object_id
@ids[block.object_id] = :true
puts @ids.keys.join(', ')
end
end

I've even tried a varient using == and ===

def l(&b)
@t ||= b
puts b == @t
puts b === @t
@t = b
end

(1..2).each { l{x=1} }

output:
true
true
false
false

How can you compare two procs that have the same body?

Thanks,
-- Tom.

--
"Nothing will ever be attempted, if all
possible objections must first be
overcome." - Samuel Johnson

"Luck is what happens when
preparation meets opportunity." - Seneca

4 Answers

Tom Jordan

8/15/2006 9:26:00 PM

0

ruby version:

ruby 1.8.4 (2006-04-14) [i386-mswin32]

On 8/15/06, Tom Jordan <tdjordan@gmail.com> wrote:
> Is there a way to compare two blocks with each other?
>
> If you promote a block into a Proc, how would you know that the
> original block was the same?
>
> This is what I want to do
>
> (1..10).each do
> once { puts "Hi Tom"}
> end
>
> I've tried to implement once like this
>
> class << self
> def once(&block)
> @ids ||= {}
> block.call unless @ids.key? block.object_id
> @ids[block.object_id] = :true
> puts @ids.keys.join(', ')
> end
> end
>
> I've even tried a varient using == and ===
>
> def l(&b)
> @t ||= b
> puts b == @t
> puts b === @t
> @t = b
> end
>
> (1..2).each { l{x=1} }
>
> output:
> true
> true
> false
> false
>
> How can you compare two procs that have the same body?
>
> Thanks,
> -- Tom.
>
> --
> "Nothing will ever be attempted, if all
> possible objections must first be
> overcome." - Samuel Johnson
>
> "Luck is what happens when
> preparation meets opportunity." - Seneca
>


--
"Nothing will ever be attempted, if all
possible objections must first be
overcome." - Samuel Johnson

"Luck is what happens when
preparation meets opportunity." - Seneca

Tom Jordan

8/16/2006 3:22:00 PM

0

On 8/15/06, Justin Collins <collinsj@seattleu.edu> wrote:
>
>
> Marshall T. Vandegrift wrote:
> > "Tom Jordan" <tdjordan@gmail.com> writes:
> >
> >
> >> Is there a way to compare two blocks with each other?
> >>
> >> If you promote a block into a Proc, how would you know that the
> >> original block was the same?
> >>
> >
> > I haven't dived into the code, but I'm pretty sure that (a) promoting
> > a block to a Proc via &block in the argument list results in a new
> > Proc each time and (b) ruby 1.8 provides no introspection into the
> > actual contents of a block.
> >
> >
> <snip>
>
> Yes, it's kind of like asking if two equations or two methods are equal.
> On the other hand, you could probably use the SerializeableProc
> (developed here: http://rubyquiz.com/q...), add an equality
> method, and then you'd have it. :)

Thanks Marshall and Justin.

This http://ruby-doc.org/core/classes/Proc.ht...

"Return true if prc is the same object as other_proc, or if they are
both procs with the same body."

led me to believe that Procs would evaluate to equality if they had
the same body.

So I would have expected that the following:

s = lambda { x = 1 }
t = lambda { x = 1 }
s == t # => true expected, false in reality

So my question is; when would the body of Procs ever be the same?

Thanks,
-- Tom.


--
"Nothing will ever be attempted, if all
possible objections must first be
overcome." - Samuel Johnson

"Luck is what happens when
preparation meets opportunity." - Seneca

Justin Collins

8/16/2006 5:03:00 PM

0

Tom Jordan wrote:
> On 8/15/06, Justin Collins <collinsj@seattleu.edu> wrote:
>>
>>
>> Marshall T. Vandegrift wrote:
>> > "Tom Jordan" <tdjordan@gmail.com> writes:
>> >
>> >
>> >> Is there a way to compare two blocks with each other?
>> >>
>> >> If you promote a block into a Proc, how would you know that the
>> >> original block was the same?
>> >>
>> >
>> > I haven't dived into the code, but I'm pretty sure that (a) promoting
>> > a block to a Proc via &block in the argument list results in a new
>> > Proc each time and (b) ruby 1.8 provides no introspection into the
>> > actual contents of a block.
>> >
>> >
>> <snip>
>>
>> Yes, it's kind of like asking if two equations or two methods are equal.
>> On the other hand, you could probably use the SerializeableProc
>> (developed here: http://rubyquiz.com/q...), add an equality
>> method, and then you'd have it. :)
>
> Thanks Marshall and Justin.
>
> This http://ruby-doc.org/core/classes/Proc.ht...
>
> "Return true if prc is the same object as other_proc, or if they are
> both procs with the same body."
>
> led me to believe that Procs would evaluate to equality if they had
> the same body.
>
> So I would have expected that the following:
>
> s = lambda { x = 1 }
> t = lambda { x = 1 }
> s == t # => true expected, false in reality
>
> So my question is; when would the body of Procs ever be the same?
>
> Thanks,
> -- Tom.
Hi Tom,

Well, I did find one instance where this works. If you use Proc#dup or
Proc#clone, you will end up with a new Proc object, but they will
evaluate to being equal:

irb(main):001:0> a = Proc.new { n = 1 }
=> #<Proc:0xb7d36224@(irb):1>
irb(main):002:0> b = a.dup
=> #<Proc:0xb7d36224@(irb):1>
irb(main):003:0> a.object_id
=> -605441814
irb(main):004:0> b.object_id
=> -605445814
irb(main):005:0> a == b
=> true
irb(main):006:0> b == a
=> true
irb(main):007:0> c = Proc.new { n = 1 }
=> #<Proc:0xb7d27ecc@(irb):7>
irb(main):008:0> d = c.clone
=> #<Proc:0xb7d27ecc@(irb):7>
irb(main):009:0> c.object_id
=> -605470914
irb(main):010:0> d.object_id
=> -605475424
irb(main):011:0> c == d
=> true
irb(main):012:0> d == c
=> true


Other than that, I don't see a way for two Procs to have the same block
(and know it). Take a look at the source for Proc#==, it's somewhat
helpful as well.

I realize this doesn't help you in the general case, though...

-Justin

Dominik Bathon

8/16/2006 5:56:00 PM

0

Hi,

On Wed, 16 Aug 2006 17:21:39 +0200, Tom Jordan <tdjordan@gmail.com> wrot=
e:

> This http://ruby-doc.org/core/classes/Proc.ht...
>
> "Return true if prc is the same object as other_proc, or if they are
> both procs with the same body."
>
> led me to believe that Procs would evaluate to equality if they had
> the same body.
>
> So I would have expected that the following:
>
> s =3D lambda { x =3D 1 }
> t =3D lambda { x =3D 1 }
> s =3D=3D t # =3D> true expected, false in reality

If you really want to check if procs have the same or equivalent bodies,=
=

you can use RubyNode (http://rubynode.ruby...):

>> p1 =3D proc { 1 + 1 }
=3D> #<Proc:0xb7a70b64@(irb):1>
>> p2 =3D proc { 1 + 1 }
=3D> #<Proc:0xb7a6e580@(irb):2>
>> require "rubynode"
=3D> true
>> p1.body_node.transform
=3D> [:call, {:args=3D>[:array, [[:lit, {:lit=3D>1}]]], :mid=3D>:+, :rec=
v=3D>[:lit, =

{:lit=3D>1}]}]
>> p1.body_node.transform =3D=3D p2.body_node.transform
=3D> true
>> p1 =3D=3D p2
=3D> false

But please be aware that the equality of the body node does not imply th=
at =

the blocks have the same closure:

>> def foo(a) proc { a } end
=3D> nil
>> p1 =3D foo(1)
=3D> #<Proc:0xb7a6217c@(irb):8>
>> p2 =3D foo(2)
=3D> #<Proc:0xb7a6217c@(irb):8>
>> p1.body_node.transform =3D=3D p2.body_node.transform
=3D> true
>> p1[]
=3D> 1
>> p2[]
=3D> 2

And it is also possible that different Ruby code parses to the same node=
=

tree:

>> p1 =3D proc { if 1 then 2 else 3 end }
=3D> #<Proc:0xb7ac83b4@(irb):17>
>> p2 =3D proc { unless 1 then 3 else 2 end }
=3D> #<Proc:0xb7ac239c@(irb):18>
>> p3 =3D proc { 1 ? 2 : 3 }
=3D> #<Proc:0xb7abec4c@(irb):19>
>> p1.body_node.transform =3D=3D p2.body_node.transform
=3D> true
>> p1.body_node.transform =3D=3D p3.body_node.transform
=3D> true
>> p2.body_node.transform =3D=3D p3.body_node.transform
=3D> true
>> p1.body_node.transform
=3D> [:if, {:else=3D>[:lit, {:lit=3D>3}], :cond=3D>[:lit, {:lit=3D>1}], =
=

:body=3D>[:lit, {:lit=3D>2}]}]


So this is probably not very useful for your once method, but interestin=
g =

anyway.

Dominik