Proc Question

As I was coding this morning, a question occured to me. Why must proc objects
have a call method? I’m sure that there’s a good reason for this, but it seems
like it would be more natural for proc objects to behave as regular methods
do and avoid the .call() syntax.

I.e.,
square = proc {|n| n * n}
square(4) # => 16

I see that [] is aliased to .call, but I find that surprising over (), which
is the more typical way of specifying arguments to a method. Perhaps having
a call method is a more object-oriented way of using proc objects?

Thanks,
Travis

Travis Whitton wrote:

As I was coding this morning, a question occured to me. Why must proc objects
have a call method? I’m sure that there’s a good reason for this, but it seems
like it would be more natural for proc objects to behave as regular methods
do and avoid the .call() syntax.

I.e.,
square = proc {|n| n * n}
square(4) # => 16

I see that is aliased to .call, but I find that surprising over (), which
is the more typical way of specifying arguments to a method. Perhaps having
a call method is a more object-oriented way of using proc objects?

Thanks,
Travis

What if you had:

def square(n)
puts “in the method…”
n * n
end

square = proc{ |n| n * n }
square(4) # call method
square.call(4) # call proc object

In this case, call() would allow you to differentiate between a method
and a proc object.

Regards,

Dan

···


a = [74, 117, 115, 116, 32, 65, 110, 111, 116, 104, 101, 114, 32, 82]
a.push(117,98, 121, 32, 72, 97, 99, 107, 101, 114)
puts a.pack(“C*”)

square(4) currently is a method call, i.e. self.square(4), or
self.call(:square,4) for the long-hand version.

What you are proposing is that foo(x) should mean foo.call(x) if ‘foo’ is a
local variable in the current scope, or self.foo(x) if not.

Whilst this is feasible, I think there is already enough syntactic magic
based on whether a local variable exists or not; I personally wouldn’t want
to see any more!

e.g.

 puts foo

uses the variable ‘foo’ if one exists with that name, or calls the method
‘self.foo’ if it doesn’t. But

 foo = 3

is always an assignment to variable ‘foo’, not a call to method ‘self.foo=(3)’

Regards,

Brian.

···

On Thu, Apr 10, 2003 at 01:20:17AM +0900, Travis Whitton wrote:

As I was coding this morning, a question occured to me. Why must proc objects
have a call method? I’m sure that there’s a good reason for this, but it seems
like it would be more natural for proc objects to behave as regular methods
do and avoid the .call() syntax.

I.e.,
square = proc {|n| n * n}
square(4) # => 16

A proc is an object. A method isn’t. Consider a method of zero arguments:

def fiveSquared
5 * 5
end

You can call this method simply by writing `fiveSquared’, and Ruby knows
you want the method called, because that’s the only thing you can do with
methods.

A proc, however, can be assigned to a variable, passed into methods, etc.
In fact, unlike methods, procs are unnamed. (Am I right about methods
intrinsically having names?) So, in the following code:

fiveSquared = proc {5 * 5}

`fiveSquared’ is just a variable.

I see your point though. It is sort of dissatisfying that procs and methods
have such different syntaxes (syntices?). Same for method parameter list
(...)' and block parameter list|…|’. Still, it’s important to realize
that methods and functions (which is what procs are) are different, even
if their underlying implementations are similar. This is an object-oriented
language, after all.

Chris

In this case, call() would allow you to differentiate between a method
and a proc object.

Hmm… you’ve got a point there. I guess adding this feature could break
some people’s code. I guess the solution would be to not create proc objects
with the same name as an existing method just the same as you shouldn’t create
2 methods with the same name inside a class. I tested your example in Python
just to see what would happen, and the method took precedence over the lambda.
If Ruby copied that behaviour, then I don’t believe any code breakage would
occur. At any rate, it’s just an idea.

Cheers,
Travis

A proc is an object. A method isn’t. Consider a method of zero arguments:

def fiveSquared
5 * 5
end

You can call this method simply by writing `fiveSquared’, and Ruby knows
you want the method called, because that’s the only thing you can do with
methods.

Well, there’s a bit more to it than that really.

If I follow your above code with:

puts fiveSquared
fiveSquared = 9 # OK so not very strong mathematically!
puts fiveSquared

Then I get “25” then “9” printed. ‘fiveSquared’ by itself is just a symbolic
reference; in the second location it’s treated as a local variable access
because of the previous assignment to fiveSquared.

But after that:

puts fiveSquared()
puts self.fiveSquared

both give 25. With a parenthesised argument list, or an explicit receiver,
it has to be interpreted as a method call; there is now no ambiguity.

Furthermore, a method (once defined) is in fact an object, or at least you
can get hold of an object which encapulates it:

m = method(:fiveSquared) #>> #<Method: Object(Object)#fiveSquared>
m.call #>> prints 25

A proc, however, can be assigned to a variable, passed into methods, etc.

Methods (like the one assigned to ‘m’ above) can be passed around too.

In fact, unlike methods, procs are unnamed. (Am I right about methods
intrinsically having names?)

I think so. The lowest-level way I know how to define a method is with
define_method(:sym,proc) so you have to assign it a symbolic name at that
point. It remembers it too (e.g. m.inspect tells you its name)

fiveSquared = proc {5 * 5}

`fiveSquared’ is just a variable.

Indeed, which happens to contain a reference to a Proc object. But even now,
fiveSquared() will still call the method, not this Proc object.

have such different syntaxes (syntices?). Same for method parameter list
(...)' and block parameter list |…|'.

The block parameter list is closer to parallel assignment than a method
call. e.g. the following are pretty much the same:

a, b, *c = 1, 2, 3, 4
… do stuff …

x = proc { |a,b,*c| … do stuff … }
x.call(1,2,3,4)

Still, it’s important to realize
that methods and functions (which is what procs are) are different

Ruby doesn’t have “functions” - it does have Methods and Procs. Someone
coming from a background of, say, C, would probably consider a Method to be
the closer analogy to a C function:

int adder(int a,b)
{
return a+b;
}

def adder(a,b)
a+b
end

as opposed to the Proc, which is perhaps a little bit like a “pointer to a
function”, but not very much :slight_smile:

Cheers,

Brian.

···

On Thu, Apr 10, 2003 at 01:57:18AM +0900, Chris Pine wrote:

“Chris Pine” nemo@hellotree.com schrieb im Newsbeitrag
news:01a001c2feb9$1a5b6f80$6401a8c0@MELONBALLER…

I see your point though. It is sort of dissatisfying that procs and
methods
have such different syntaxes (syntices?). Same for method parameter
list

Synthetics! :slight_smile:

robert

Well, there’s a bit more to it than that really.

···

----- Original Message -----
From: “Brian Candler” B.Candler@pobox.com

You can call this method simply by writing `fiveSquared’, and Ruby knows
you want the method called, because that’s the only thing you can do with
methods.


Yes, but your explanation has more to do with how Ruby determines what’s a
method and what’s a variable. I just meant that there’s nothing you can do
with methods but call them; that they aren’t objects.


Furthermore, a method (once defined) is in fact an object, or at least you
can get hold of an object which encapulates it:


Which isn’t quite the same thing… of course instances of the Method class
are objects. In fact:

irb(main):001:0> method(:puts).id
=> 537316732
irb(main):002:0> method(:puts).id
=> 537311592

Method objects wrap methods.


have such different syntaxes (syntices?). Same for method parameter list
(...)' and block parameter list |…|'.

The block parameter list is closer to parallel assignment than a method
call. e.g. the following are pretty much the same:

I don’t know what you mean by that. They are all three similar, as is this:

irb(main):003:0> a = [3,4,5]
=> [3, 4, 5]
irb(main):004:0> b = [1,2,*a]
=> [1, 2, 3, 4, 5]

Because they all use arrays (as I understand it). How about this?

irb(main):005:0> case 3
irb(main):006:1> when *b then puts ‘yep’
irb(main):007:1> end
yep
=> nil

The beginning of a method binds the parameters to the arguments passed in (I
hope I’m getting my vocabulary right) in exactly the same way, again, as I
understand it.


Ruby doesn’t have “functions” - it does have Methods and Procs.

What do you think a proc is? You can even create one with lambda'! We all agree that they are closures, right? Closures are functions (with certain properties, of course) by any definition I have ever seen. A proc is just a wrapped function, and you call it (the function) with the call’ method
(i.e. calling the proc’s method).

I don’t think OO purity is achieved by:
alias :proc :function

:slight_smile:

Methods, on the other hand, seem quite different to me (even if they are
implemented with procs much like parameter lists are implemented with
arrays). It seems like, instead of being bound to any particular
environment, they are just bound “to the object”. Plus, they are shared
between all objects of that class… that’s a big difference. You would
need a different proc for each object to get the same effect.

Chris

The block parameter list is closer to parallel assignment than a method
call. e.g. the following are pretty much the same:

I don’t know what you mean by that. They are all three similar, as is this:

irb(main):003:0> a = [3,4,5]
=> [3, 4, 5]
irb(main):004:0> b = [1,2,*a]
=> [1, 2, 3, 4, 5]

Because they all use arrays (as I understand it).

I thought what you were highlighting was the difference between the syntax
of method calls and proc parameters. There are several differences in the
way arity is handled, for example. I was just pointing out that if you
compare proc parameters to parallel assignments, rather than method calls,
they are identical.

I too feel there could perhaps be a more unified underlying handling, and
indeed I do get caught out occasionally by

foo.each do |v| .... end

where foo is a hash, and I end up getting [key,value] passed in when I would
rather have an argument error. But pragmatically I see cases where this is
also useful.

The beginning of a method binds the parameters to the arguments passed in (I
hope I’m getting my vocabulary right) in exactly the same way, again, as I
understand it.

They don’t work in exactly the same way. For example:

def test(a)
puts a.inspect
end
test(1,2) #>> ArgumentError: wrong # of arguments(2 for 1)

test = proc{|a| puts a.inspect}
test.call(1,2) #>> [1, 2]


Ruby doesn’t have “functions” - it does have Methods and Procs.

What do you think a proc is? You can even create one with `lambda’! We all
agree that they are closures, right? Closures are functions (with certain
properties, of course) by any definition I have ever seen.

I think perhaps we are just coming from different backgrounds - yours
mathematics/computer science, mine programming (and low-level at that)

In C, a function is a named procedure which takes arguments, performs some
operations, and (optionally) returns a value. In Ruby, that’s a method. To
you, the word ‘function’ may mean something else.

Ruby doesn’t in itself have anything called a ‘function’ that I am aware of,
so if you choose to apply that label to a Proc then fine; but I choose to
apply it to a Method :slight_smile:

A proc is just a
wrapped function, and you call it (the function) with the `call’ method
(i.e. calling the proc’s method).

And then you can also argue that a method is just a wrapped proc; this is
explicit if you say

self.class.instance_eval { define_method(:foo, proc { |x| x*2 }) }

rather than the more sugary

def foo(x)
x*2
end

Once it has become a Method it gains additional properties though, as you
point out below.

Methods, on the other hand, seem quite different to me (even if they are
implemented with procs much like parameter lists are implemented with
arrays). It seems like, instead of being bound to any particular
environment, they are just bound “to the object”. Plus, they are shared
between all objects of that class… that’s a big difference. You would
need a different proc for each object to get the same effect.

Sure. You have instance methods shared between all objects of that class,
and you have singleton methods associated with a single object. I wasn’t
trying to say that Procs and Methods were the same, as they clearly
aren’t… sorry if it came across that way!

Regards,

Brian.

···

On Thu, Apr 10, 2003 at 05:59:04AM +0900, Chris Pine wrote: