Proc comparison

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:[email protected]_test.rb:15
t2 action: #Proc:[email protected]_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?

On Sat, 6 Oct 2007 04:22:50 +0900, Chris H.
[email protected] wrote:

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

Mental G. wrote:

On Sat, 6 Oct 2007 04:22:50 +0900, Chris H.
[email protected] wrote:

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

so then is there no way to compare the contents?

On Sat, 6 Oct 2007 04:36:39 +0900, Chris H.
[email protected] wrote:

so then is there no way to compare the contents?

Not cleanly. Why do you want to?

-mental

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

On Sat, 2007-10-06 at 04:49 +0900, Sylvain J. wrote:

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.

Ah, good catch!

-mental

Mental G. wrote:

On Sat, 6 Oct 2007 04:36:39 +0900, Chris H.
[email protected] wrote:

so then is there no way to compare the contents?

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).

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

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.

Sylvain J. wrote:

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

Chris H. wrote:

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

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs