(oddity) applying objects with #call() implicitly

G

gabriele renzi

Hi gurus and nubys,

lurking comp.lang.misc, I noticed this message:
http://tinyurl.com/2q8c7

and suddenly had the vision to have that in ruby too.
What I'm talking about is application of callable objects.
As of now we have to explicitly write:

callable.call arg1, arg2

and it feels ugly.

I was going to ask if we could have this:
callable arg1,arg2 # implicitly looks for #call
callable # the callable object
callable() # forces application with zero arguments
....

what's wrong with this?


PS
also, was'nt Marcin 'Qrczak' Kowalczyk on this list long time ago? :)
 
R

Robert Klemme

gabriele renzi said:
Hi gurus and nubys,

lurking comp.lang.misc, I noticed this message:
http://tinyurl.com/2q8c7

and suddenly had the vision to have that in ruby too.
What I'm talking about is application of callable objects.
As of now we have to explicitly write:

callable.call arg1, arg2

and it feels ugly.

I was going to ask if we could have this:
callable arg1,arg2 # implicitly looks for #call
callable # the callable object
callable() # forces application with zero arguments
...

what's wrong with this?

Ambiguity. "callable arg1,arg2" denotes an invocation of the method
"callable" of "self". "callable()" also invokes the same method albeit
without arguments.

However, you can use #[] like this:
callable = lambda {|*args| puts "Seen #{args.inspect}"}
=> # said:
callable[ "foo", "bar" ]
Seen ["foo", "bar"]
=> nil

Regards

robert
 
G

gabriele renzi

il Mon, 28 Jun 2004 13:37:21 +0200, "Robert Klemme" <[email protected]>
ha scritto::


Ambiguity. "callable arg1,arg2" denotes an invocation of the method
"callable" of "self". "callable()" also invokes the same method albeit
without arguments.

well, but ambiguity exists anyway, just think of :

print p

"p" may stand for self#p, or a local variable named "p".

More, using a method passed in via argument won't be different from
defining a new one in the current scope explicitly (actually, a method
def in a method ends up in the self scope), I mean: it's up to the
user to be smart enough, writing something like:

def comb(fun1,fun2)

instead of
def comb(print,puts)
However, you can use #[] like this:

yes, I know, but using #[] is somewhat even worst than #call.

It is better because it looks like () yet it's worst because it just
mimics something hiding it's meaning, whereas #call at least is
explicit.
 
R

Robert Klemme

gabriele renzi said:
il Mon, 28 Jun 2004 13:37:21 +0200, "Robert Klemme" <[email protected]>
ha scritto::




well, but ambiguity exists anyway, just think of :

print p

"p" may stand for self#p, or a local variable named "p".

True. It might be inconsistency then, because for a method "foo" and
"foo()" are identical (apart from, that the latter form does not have the
ambiguity) but you proposed change would introduce a significant
difference between "foo" and "foo()".

You probably guessed that I don't like this very much. :) Well, there
are also reasons: ruby could no longer determine at compile time the
semantics of this code:

def foo(x)
x("bar")
end

Because x("bar") could be a method invocation or it could be an invocation
of the Proc instance x. And since we don't have type declarations in Ruby
you couldn't get this to work. That's especially true because when foo is
defined there need not be a method x at all.

(Dunno whether that was clear enough - I'm still sorting this out...)
More, using a method passed in via argument won't be different from
defining a new one in the current scope explicitly (actually, a method
def in a method ends up in the self scope), I mean: it's up to the
user to be smart enough, writing something like:

def comb(fun1,fun2)

instead of
def comb(print,puts)
However, you can use #[] like this:

yes, I know, but using #[] is somewhat even worst than #call.

It is better because it looks like () yet it's worst because it just
mimics something hiding it's meaning,

Could you elaborate that? I don't get the point. My understanding was,
that you were looking for a nicer more intuitive syntax to invoke a Proc
instance.
whereas #call at least is
explicit.

That's true. I don't have a problem with #call. :)

Kind regards

robert
 
F

Florian Gross

gabriele said:
well, but ambiguity exists anyway, just think of :
print p
"p" may stand for self#p, or a local variable named "p".

This case can be resolved fairly easily. (If there's an assignment to p
then it is a variable)

However think about this case:

def foo
puts 0
lambda { puts 1; lambda { puts 2; lambda { puts 3 }}}
end

foo # What will this do?
foo() # What will this do?
x = foo; x # What will this do?
x = foo; x() # What will this do?
x = foo(); x # What will this do?
x = foo(); x() # What will this do?
x = foo; y = x; y # What will this do?
x = foo(); y = x; y # What will this do?
x = foo(); y = x(); y # What will this do?
x = foo; y = x(); y # What will this do?
x = foo; y = x(); y() # What will this do?
x = foo; y = x; y() # What will this do?
x = foo(); y = x(); y # What will this do?
x = foo(); y = x(); y() # What will this do?

Etc. -- there are many cases here.

I think the problem is that you can't have optional ()-arguments and ()
as a call operator as the same time.

However we need optional () because of things like this:

class Foo
attr_accessor :bar
end
obj = Foo.new; obj.bar # Do you want to type obj.bar() instead?
obj = Foo.new; obj.bar = 5; # Do you want to type obj.bar=(5) instead?

In other ways: To have this in Ruby we would need to get rid of our
method-as-accessors model which I think is a big advantage of Ruby.

Regards,
Florian Gross
 
G

gabriele renzi

gabriele renzi wrote:

This case can be resolved fairly easily. (If there's an assignment to p
then it is a variable)

Yes, and if there is a variable named "foo" in
foo arg1
then it is calling that one instead of the old 'foo' method.
However think about this case:

def foo
puts 0
lambda { puts 1; lambda { puts 2; lambda { puts 3 }}}
end

foo # What will this do?
0 #=> # said:
foo() # What will this do?
0 #=> # said:
x = foo; x # What will this do?
0 #=> # said:
x = foo; x() # What will this do?
01 #=> # said:
x = foo(); x # What will this do?
0 #=> # said:
x = foo(); x() # What will this do?
01 #=> # said:
x = foo; y = x; y # What will this do?
0 #=> # said:
x = foo(); y = x; y # What will this do?
0 #=> # said:
x = foo(); y = x(); y # What will this do?
01 #=> # said:
x = foo; y = x(); y # What will this do?
01 #=> # said:
x = foo; y = x(); y() # What will this do?
012 #=> # said:
x = foo; y = x; y() # What will this do?
01 #=> # said:
x = foo(); y = x(); y # What will this do?
01 #=> # said:
x = foo(); y = x(); y() # What will this do?
012 #=> # said:
Etc. -- there are many cases here.

yes, but the rule is quite simple :)

Note that I may have 'computed' the things myself and I may be wrong.
Anyway, sample implementation:
0
0
0
1
0
1
0
0
1
0
1
2
0
1
2
=> # said:
I think the problem is that you can't have optional ()-arguments and ()
as a call operator as the same time.

this is what I usually thought. After reading the msg [see first msg]
I changed slightly my mind.
However we need optional () because of things like this:

<snip>
yes, totally agree.
 
G

gabriele renzi

oh, note that the 'lookup order' in the sample is different from what
I proposed.
I'm quite open to that choice, I think the former would be better, but
I just know how to implement a sample of the latter ;)
 
G

gabriele renzi

True. It might be inconsistency then, because for a method "foo" and
"foo()" are identical (apart from, that the latter form does not have the
ambiguity) but you proposed change would introduce a significant
difference between "foo" and "foo()".

this is true. It feels better to me, somehow, but that's just my
opinion.
You probably guessed that I don't like this very much. :)

You don't like my idea! You #ò@*
It's ok for anyone to dislike this, we're just chatting about an idea,
nothing really important[1] :)
Well, there
are also reasons: ruby could no longer determine at compile time the
semantics of this code:

def foo(x)
x("bar")
end

Because x("bar") could be a method invocation or it could be an invocation
of the Proc instance x.
And since we don't have type declarations in Ruby
you couldn't get this to work. That's especially true because when foo is
defined there need not be a method x at all.


I see, even if I fail to see how this is a problem. Say, #x could not
be defined at the time of #foo call, so ruby has to check for
something anyway. In what it differs from checking the type of x ?

Could you elaborate that? I don't get the point. My understanding was,
that you were looking for a nicer more intuitive syntax to invoke a Proc
instance.

not a nicer as in 'less typing'. just nicer as in 'mimic the right
thing', say:


foo 10
and
foo(10)
and
foo.call 10

all gives me the feeling of a method call/function application, where
foo[10]

is array indexing to me.
Obviously the inconsistency is not really removed using the trick I
propose, just moved somewhere else. It just happens I'd prefer seeing
it there instead of here :)


[1] ok, people use to die for Ideas, but that ones are capitalized.
 
F

Florian Gross

gabriele said:
0

01 #=> #<Proc2>

So (foo)() and foo() aren't the same thing any more? It feels a bit
inconsistent IMHO.

Also foo would be the same as foo() in your case if foo is a method,
but it would be something totally different if it is a lambda.

I think that a solution to this problem should make "def x; 5; end" and
"x = lambda { 5 }" as equivalent as possible.

But of course I am not matz so I'm not the one to judge over this anyway.

Maybe you could do a RCR? :)

Regards,
Florian Gross
 
G

gabriele renzi

il Mon, 28 Jun 2004 21:41:30 +0200, Florian Gross <[email protected]> ha
scritto::

So (foo)() and foo() aren't the same thing any more? It feels a bit
inconsistent IMHO.

er.. actually they are not the same even now :)

irb(main):001:0> def foo
irb(main):002:1> end
=> nil
irb(main):003:0> (foo)()
SyntaxError: compile error
(irb):3: syntax error
(foo)()
^
from (irb):3
Also foo would be the same as foo() in your case if foo is a method,
but it would be something totally different if it is a lambda.

I think that a solution to this problem should make "def x; 5; end" and
"x = lambda { 5 }" as equivalent as possible.

yes, but I did not came up with such a good solution. Maybe we need an
AI module.
But of course I am not matz so I'm not the one to judge over this anyway.

Maybe you could do a RCR? :)

mh.. two people answered and both were against this. Should I ? :)
 
F

Florian Gross

gabriele said:
yes, but I did not came up with such a good solution. Maybe we need an
AI module.

Do we already have path finding modules that will work generally? That
could help a lot. :)
mh.. two people answered and both were against this. Should I ? :)

I think it would be neat and I actually think that is quite neat in both
JavaScript and Python, but I still doubt that it could work correctly in
Ruby.

I'd be for this if you can find the one solution that will perfectly
integrate with Ruby. ;)

Regards,
Florian Gross
 
S

Sean O'Dell

Ambiguity. "callable arg1,arg2" denotes an invocation of the method
"callable" of "self". "callable()" also invokes the same method albeit
without arguments.

Couldn't ambiguity be resolved by giving the callable object priority over a
method, and using self to call the object#method?

class MyClass
def mymethod
p "object#mymethod"
end

def anothermethod(mymethod)
mymethod # => "object#call"
self.mymethod # => "object#mymethod"
end
end

class CallableClass
def call()
p "object#call"
end
end

o1 = CallableClass.new
o2= MyClass.new

o2.anothermethod(o1)



Sean O'Dell
 
F

Florian Gross

Sean said:
Ambiguity.
Couldn't ambiguity be resolved by giving the callable object priority over a
method, and using self to call the object#method?

[...]
def anothermethod(mymethod)
mymethod # => "object#call"
self.mymethod # => "object#mymethod"
end
end

There's still an ambiguity problem with this: When using "mymethod" you
could also want to refer to the "mymethod" argument *without* calling it
at the same time.

Regards,
Florian Gross
 
S

Sean O'Dell

Sean said:
I was going to ask if we could have this:
callable() # forces application with zero arguments
what's wrong with this?

Ambiguity.

Couldn't ambiguity be resolved by giving the callable object priority
over a method, and using self to call the object#method?

[...]
def anothermethod(mymethod)
mymethod # => "object#call"
self.mymethod # => "object#mymethod"
end
end

There's still an ambiguity problem with this: When using "mymethod" you
could also want to refer to the "mymethod" argument *without* calling it
at the same time.

Could mymethod mean the object and mymethod() be used to make the method call?
That was gabriele's suggestion; could that still be used, using self to
differentiate the callable object call from the self.method call?

Sean O'Dell
 
R

Robert Klemme

gabriele renzi said:
this is true. It feels better to me, somehow, but that's just my
opinion.

The nice thing about such discussions is that we all can rationalize our
feelings - or discover that they were wrong.
You probably guessed that I don't like this very much. :)

You don't like my idea! You #ò@*
It's ok for anyone to dislike this, we're just chatting about an idea,
nothing really important[1] :)

Gulp... :)
I see, even if I fail to see how this is a problem. Say, #x could not
be defined at the time of #foo call, so ruby has to check for
something anyway. In what it differs from checking the type of x ?

Ruby determines locally, i.e. considering only the method it currently
compiles, how to interpret artefacts. It doesn't matter if there is no
method x() if you do "def foo; x("bar"); end"; this is recognized as a
method call. Only at runtime it is checked whether there is a method x.
But the invocation code is compiled at this stage.

Now, if we introduce your change, Ruby cannot determine whether to compile
the equivalent of self.x("bar") or of x.call("bar") because it's clear
only at runtime what x is.
Could you elaborate that? I don't get the point. My understanding was,
that you were looking for a nicer more intuitive syntax to invoke a Proc
instance.

not a nicer as in 'less typing'. just nicer as in 'mimic the right
thing', say:


foo 10
and
foo(10)
and
foo.call 10

all gives me the feeling of a method call/function application, where
foo[10]

is array indexing to me.

.... or associative lookup (aka Hash). From a certain point of view this
is pretty much the same: you hand it over some values and get something
back (if you're lucky).
Obviously the inconsistency is not really removed using the trick I
propose, just moved somewhere else. It just happens I'd prefer seeing
it there instead of here :)


[1] ok, people use to die for Ideas, but that ones are capitalized.

Hopefully you won't die for this idea. :)

Kind regards

robert
 
J

Jean-Hugues ROBERT

Ambiguity. "callable arg1,arg2" denotes an invocation of the method
"callable" of "self". "callable()" also invokes the same method albeit
without arguments.

well, but ambiguity exists anyway, just think of :

print p

"p" may stand for self#p, or a local variable named "p".

More, using a method passed in via argument won't be different from
defining a new one in the current scope explicitly (actually, a method
def in a method ends up in the self scope), I mean: it's up to the
user to be smart enough, writing something like:

def comb(fun1,fun2)

instead of
def comb(print,puts)
However, you can use #[] like this:

yes, I know, but using #[] is somewhat even worst than #call.

It is better because it looks like () yet it's worst because it just
mimics something hiding it's meaning, whereas #call at least is
explicit.

It may look more understandable if you think of [] as of
a "dereference" operator. In my rcr.rb I added a:
class Proc
def []=( *args )
self[*args]
end
end
... so that a Proc can act as a lvalue, much like a
method can.
xxx[] reads as "content of xxx"
xxx[] = yyy reads as "set content of xxx to yyy"

This is the closer to a "transparent" dereferencing
scheme I managed to get so far.

Yours,

JeanHuguesRobert
 

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

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top