Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is `Proc#==` evaluated?

How is Proc#== evaluated? RDoc says:

prc == other_proc → true or false

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

But it is not clear what counts as having "the same body". One condition seems to be that the arity must be the same:

->{} == ->{} # => true
->{} == ->x{} # => false
->x{} == ->x{} # => true
->x{} == ->y{} # => true
->x{} == ->y,z{} # => false

But there is more than that. As RDoc says, the body matters:

->{nil} == ->{nil} # => true
->{nil} == ->{false} # => false
->{false} == ->{false} # => true

But at the same time, it looks like the proc is not fully evaluated:

->{} == ->{nil} # => false
->{false} == ->{1 == 2} # => false

To what extent is the body evaluated?

like image 988
sawa Avatar asked Jan 23 '13 19:01

sawa


People also ask

What is proc process?

Proc file system (procfs) is virtual file system created on fly when system boots and is dissolved at time of system shut down. It contains useful information about the processes that are currently running, it is regarded as control and information center for kernel.

What is proc used for?

The proc file system acts as an interface to internal data structures in the kernel. It can be used to obtain information about the system and to change certain kernel parameters at runtime (sysctl).

How does proc file system work?

proc is a special file system and is not associated with any hard drive device. Certian files inside /proc can be modified to change the behaviour of a running kernel. For example, /proc/sys/ files. Most of the system monitoring commands like ps, top, free, etc use process files inside /proc/ to fetch information.

Where is proc located?

The Linux /proc File System is a virtual filesystem that exists in RAM (i.e., it is not stored on the hard drive). That means that it exists only when the computer is turned on and running.


2 Answers

This has changed in Ruby 2.0, so you should not try to compare Procs. They won't be == unless they are exactly the same object.

The discussion can be found here.

If you really need to compare the code of two blocks and are using MRI, you can play around with RubyVM::InstructionSequence.disassemble(block), or even better in Ruby 2.0 RubyVM::InstructionSequence.of(block).

like image 57
Marc-André Lafortune Avatar answered Oct 27 '22 07:10

Marc-André Lafortune


To answer that question lets look at the proc comparison code

static VALUE
proc_eq(VALUE self, VALUE other)
{
    if (self == other) {
        return Qtrue;
    }
    else {
        if (rb_obj_is_proc(other)) {
           rb_proc_t *p1, *p2;
           GetProcPtr(self, p1);
           GetProcPtr(other, p2);
           if (p1->envval == p2->envval &&
              p1->block.iseq->iseq_size == p2->block.iseq->iseq_size &&
              p1->block.iseq->local_size == p2->block.iseq->local_size &&
              MEMCMP(p1->block.iseq->iseq, p2->block.iseq->iseq, VALUE,
                    p1->block.iseq->iseq_size) == 0) {
                 return Qtrue;
           }
       }
    }
    return Qfalse;
}

The first if branch is quite simple - compare it two procs are the same object. The second is little bit more tricky. It checks that both of the procs have same envval, size of the iseq(proc implementation), local variables size and compares that the both implementations are identical. That means that proc equality is checked on a syntax level, not on proc result.

Lets take https://gist.github.com/4611935 First sample works just fine because number of local variables are the same and the sequence of operations are the same. Assign 123 to local variable. The second sample treated as not same because operation sequence differs - you assign 123 to different variables.

But yes, proc comparison is pretty confusing and has been removed form ruby 2.0 I presume. Now procs are compared as a regular object by its id.

like image 29
Sigurd Avatar answered Oct 27 '22 05:10

Sigurd