Proc comparison

C

Chris Hall

i'm having an issue where i need to compare 2 objects by comparing a
Proc which is stored in an instance var. however, everything i have
tried results in a false comparison.

simple example:

class Test
attr :action

def initialize(&block)
@action = block_given? ? block : nil
end

def ==(obj)
if obj.is_a?(Test)
return @action.eql?(obj.action)
end
end
end

t1 = Test.new { puts "hello" }
t2 = Test.new { puts "hello" }

puts "comp: #{t1 == t2}"
puts "t1 action: #{t1.action}"
puts "t2 action: #{t2.action}"



output:

comp: false
t1 action: #<Proc:0x00025134@eql_test.rb:15>
t2 action: #<Proc:0x0002501c@eql_test.rb:16>


when the objects are created, i use the same block of code when i create
each instance, however, it obvious that from the comparison output they
aren't the same. my question, how do i get the comparison i'm looking
for?
 
M

MenTaLguY

when the objects are created, i use the same block of code when i create
each instance, however, it obvious that from the comparison output they
aren't the same. my question, how do i get the comparison i'm looking
for?

Even though the two blocks have the same contents, they aren't the same
block because they are written in different places in the file.

-mental
 
C

Chris Hall

Mental said:
Even though the two blocks have the same contents, they aren't the same
block because they are written in different places in the file.

-mental

so then is there no way to compare the contents?
 
S

Sylvain Joyeux

Even though the two blocks have the same contents, they aren't the same
block because they are written in different places in the file.
That's not the only thing. Proc#== returns false if the bindings differ as
well. So ...

If you want to compare regardless of the binding, you can check
Proc#same_body? in utilrb

http://utilrb.rubyforge.org/utilrb/classes/Proc.html


[~]% cat bla.rb
require 'utilrb/common'
def to_proc(&block)
block
end

a, b = (1..2).map { to_proc { 10 } }
puts(a == b)
puts(a.same_body?(b))

[~]% ruby bla.rb
false
true

Sylvain
 
M

MenTaLguY

--=-ACJ/Yh2cwpV/dzDRRYLD
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

That's not the only thing. Proc#=3D=3D returns false if the bindings diff= er as=20
well.

Ah, good catch!

-mental

--=-ACJ/Yh2cwpV/dzDRRYLD
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQBHBuoVSuZBmZzm14ERAhFaAKDOf5s/rhs+A3aC0c6SkPqgiKJt/ACgyIEF
hrC3gmS+PVv1zVasRrP6A2U=
=6qCO
-----END PGP SIGNATURE-----

--=-ACJ/Yh2cwpV/dzDRRYLD--
 
C

Chris Hall

Mental said:
Not cleanly. Why do you want to?

-mental

i'm building a system to manage 'tasks' where each task has an action
(block) that it does. this action is defined when the task is
initialized:

t = Task.new:)task1) { |task| puts "i am a task that does something" }

but i don't want the system to be able to have tasks that have the same
'action' as this would cause problems. i currently name the tasks and
can test if tasks have the same name, but that doensn't stop them from
having the same block of code (action).
 
W

Wolfgang Nádasi-Donner

Chris said:
but i don't want the system to be able to have tasks that have the same
'action' as this would cause problems. i currently name the tasks and
can test if tasks have the same name, but that doensn't stop them from
having the same block of code (action).

But even if the code block is textual different, it can have the same
semantics. E.g....

procs = [
lambda{|i|(0..i-1)},
lambda{|j|(0..j-1)},
lambda{|*p|(0..p[0]-1)},
lambda{|i|Range.new(0,i-1)}
]
procs.each{|p|p p.call(5)} # => outputs four times "0..4"

Yot try to compare semantic behaviour by comparing textual code
representation - this does not work.

Wolfgang Nádasi-Donner
 
S

Sylvain Joyeux

but i don't want the system to be able to have tasks that have the same
'action' as this would cause problems. i currently name the tasks and
can test if tasks have the same name, but that doensn't stop them from
having the same block of code (action).
Define "action".

If "action" is "effect on the world", the blocks can change their own
internal state, in which case

Task() do
puts "This changes external state"
# This does not
i = 0
end
Task() do
puts "This changes external state"
# This does not
i = 1
end

would have the same action, but both blocks are different from a textual
point of view.

Sylvain
 
C

Chris Hall

I see where everyone is going with this. I agree that even if it can be
done at some level, it's most likely pointless. I'm really not too
worried about trying to stop people (most likely just myself) from doing
any 'damage'.

an more detailed example of an action might be to do some db management
tasks. it's a situation where i wouldn't want 2 tasks doing the same
thing to be defined. but obviously there is no way to really stop it.

thanks to all that replied.
 

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

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top