Eta expansion, meet overloading

118 views
Skip to first unread message

Jason Zaugg

unread,
Apr 3, 2011, 5:48:48 PM4/3/11
to scala-l...@googlegroups.com
How is `foo _` resolved if `foo` is overloaded?

I can't find this in the spec, nor infer the logic from these examples:

https://gist.github.com/900853

-jason

Miles Sabin

unread,
Apr 3, 2011, 6:06:54 PM4/3/11
to scala-l...@googlegroups.com, Jason Zaugg

A target type will resolve the overload,

scala> object OL { def foo() = ""; def foo(a: Any) = "" }
defined module OL

scala> OL.foo _
res0: () => java.lang.String = <function0>

scala> OL.foo _ : (Any => String)
res1: (Any) => String = <function1>

scala> object OL { def foo(a: Any) = ""; def foo(a: Any, b: Any) = "" }
defined module OL

scala> OL.foo _
res2: (Any, Any) => java.lang.String = <function2>

scala> OL.foo _ : (Any => String)
res3: (Any) => String = <function1>

I have to agree that the choice of overload appears somewhat arbitrary
in the absence of a guiding type annotation.

Cheers,


Miles

--
Miles Sabin
tel: +44 7813 944 528
gtalk: mi...@milessabin.com
skype: milessabin
http://www.chuusai.com/
http://twitter.com/milessabin

Paul Phillips

unread,
Apr 3, 2011, 6:24:28 PM4/3/11
to scala-l...@googlegroups.com, Jason Zaugg
On 4/3/11 2:48 PM, Jason Zaugg wrote:
> How is `foo _` resolved if `foo` is overloaded?
>
> I can't find this in the spec, nor infer the logic from these examples:

Here are a few more which will shed absolutely no light on anything.

scala> object OL { def foo(a: Int) = ""; def foo(a: Int, b: Int) = "" }
defined module OL

scala> OL.foo _
<console>:9: error: ambiguous reference to overloaded definition,
both method foo in object OL of type (a: Int,b: Int)java.lang.String
and method foo in object OL of type (a: Int)java.lang.String
match expected type ?
OL.foo _
^

scala> object OL { def foo(a: Int) = ""; def foo(a: AnyRef, b: Int) = "" }
defined module OL

scala> OL.foo _
<console>:9: error: ambiguous reference to overloaded definition,
both method foo in object OL of type (a: AnyRef,b: Int)java.lang.String
and method foo in object OL of type (a: Int)java.lang.String
match expected type ?
OL.foo _
^

scala> object OL { def foo(a: AnyRef) = ""; def foo(a: Int, b: Int) = "" }
defined module OL

scala> OL.foo _
res10: (Int, Int) => java.lang.String = <function2>

Jason Zaugg

unread,
Apr 3, 2011, 6:30:08 PM4/3/11
to Paul Phillips, scala-l...@googlegroups.com
On Mon, Apr 4, 2011 at 12:24 AM, Paul Phillips <pa...@improving.org> wrote:
> On 4/3/11 2:48 PM, Jason Zaugg wrote:
>>
>> How is `foo _` resolved if `foo` is overloaded?
>>
>> I can't find this in the spec, nor infer the logic from these examples:
>
> Here are a few more which will shed absolutely no light on anything.

Perhaps deprecation would be more straightforward than specification.

-jason

Paul Phillips

unread,
Apr 3, 2011, 6:44:45 PM4/3/11
to Jason Zaugg, scala-l...@googlegroups.com
On 4/3/11 3:30 PM, Jason Zaugg wrote:
> Perhaps deprecation would be more straightforward than specification.

Oh, you and martin are real opinion buddies on this one. Everyone wants
to deprecate poor trailing underscore. I will contrive an example of
why I would miss it. (I use this power in the repl with some frequency.
I guess I could keep faking it in the repl even if it were gone.)


// do dee do, thinking about plumping f up a bit
scala> class A { def f(x1: Int, x2: Int, x3: Int) = x1+x2+x3 }
defined class A

scala> def g(x: A) = x.f _
g: (x: A)(Int, Int, Int) => Int

// I'm doing it! Four! Four value parameters! A ha ha!
scala> class A { def f(x1: Int, x2: Int, x3: Int, x4: Int) = x1+x2+x3+x4 }
defined class A

// Wow, it's source compatible. Abstraction over arity!
// Practcally the only one we have!
scala> def g(x: A) = x.f _
g: (x: A)(Int, Int, Int, Int) => Int

// But without that power, we are sad pandas
scala> class A { def f(x1: Int, x2: Int, x3: Int) = x1+x2+x3 }
defined class A

// g: "I'm grouchy, verbose, and set in my ways. Three, no more no less."
scala> def g(x: A) = x.f(_, _, _)
g: (x: A)(Int, Int, Int) => Int

scala> class A { def f(x1: Int, x2: Int, x3: Int, x4: Int) = x1+x2+x3+x4 }
defined class A

// Ay caramba, error splosion.
scala> def g(x: A) = x.f(_, _, _)

<console>:8: error: missing parameter type for expanded function ((x$1,
x$2, x$3) => x.f(x$1, x$2, x$3))
def g(x: A) = x.f(_, _, _)
^
<console>:8: error: missing parameter type for expanded function ((x$1:
<error>, x$2, x$3) => x.f(x$1, x$2, x$3))
def g(x: A) = x.f(_, _, _)
^
<console>:8: error: missing parameter type for expanded function ((x$1:
<error>, x$2: <error>, x$3) => x.f(x$1, x$2, x$3))
def g(x: A) = x.f(_, _, _)
^
<console>:8: error: not enough arguments for method f: (x1: Int,x2:
Int,x3: Int,x4: Int)Int.
Unspecified value parameter x4.
def g(x: A) = x.f(_, _, _)
^

Jim Powers

unread,
Apr 3, 2011, 9:38:35 PM4/3/11
to scala-l...@googlegroups.com, Paul Phillips, Jason Zaugg
On Sun, Apr 3, 2011 at 6:44 PM, Paul Phillips <pa...@improving.org> wrote:
On 4/3/11 3:30 PM, Jason Zaugg wrote:
Perhaps deprecation would be more straightforward than specification.

Oh, you and martin are real opinion buddies on this one.  Everyone wants to deprecate poor trailing underscore.  I will contrive an example of why I would miss it.  (I use this power in the repl with some frequency.  I guess I could keep faking it in the repl even if it were gone.)

I too would miss trailing underscore unless it actually wasn't necessary.  The compiler already complains when you omit it: 

scala> class A { def f(x1: Int, x2: Int, x3: Int) = x1+x2+x3 }  
defined class A

scala> def g(x: A) = x.f
<console>:6: error: missing arguments for method f in class A;
follow this method with `_' if you want to treat it as a partially applied function
       def g(x: A) = x.f

I'm sure that there is something in the spec or some other obvious reason why it cannot work, but it would be nice if x.f in the above did the expected thing and just return the same thing as x.f _.

--
Jim Powers

Jim Powers

unread,
Apr 3, 2011, 9:44:21 PM4/3/11
to scala-l...@googlegroups.com
Yes, this destroys my dream:

scala> class A { def f = 5 }                                    
defined class A

scala> def g(x: A) = x.f      
g: (x: A)Int

Like I said, clearly something obvious gets in the way of my dream.

--
Jim Powers

Chris Twiner

unread,
Apr 4, 2011, 4:03:46 AM4/4/11
to scala-l...@googlegroups.com, Jason Zaugg

I don't want to be a sad panda _

On 4 Apr 2011 00:44, "Paul Phillips" <pa...@improving.org> wrote:

On 4/3/11 3:30 PM, Jason Zaugg wrote:
>

> Perhaps deprecation would be more straightforward than spe...

Jason Zaugg

unread,
Apr 4, 2011, 4:11:37 AM4/4/11
to Chris Twiner, scala-l...@googlegroups.com
On Mon, Apr 4, 2011 at 10:03 AM, Chris Twiner <chris....@gmail.com> wrote:
> I don't want to be a sad panda _
>
> On 4 Apr 2011 00:44, "Paul Phillips" <pa...@improving.org> wrote:
>
> On 4/3/11 3:30 PM, Jason Zaugg wrote:
>>
>> Perhaps deprecation would be more straightforward than spe...
>
> Oh, you and martin are real opinion buddies on this one.  Everyone wants to
> deprecate poor trailing underscore.  I will contrive an example of why I
> would miss it.  (I use this power in the repl with some frequency.  I guess
> I could keep faking it in the repl even if it were gone.)

For the record, I'm only advocating a deprecation in the case of an
overloaded panda. Who is probably already sad.

-jason

Johannes Rudolph

unread,
Apr 4, 2011, 4:43:21 AM4/4/11
to scala-l...@googlegroups.com, Jason Zaugg, Chris Twiner
On Mon, Apr 4, 2011 at 10:11 AM, Jason Zaugg <jza...@gmail.com> wrote:
> For the record, I'm only advocating a deprecation in the case of an
> overloaded panda. Who is probably already sad.

Good to know! I wouldn't be too happy as well to lose the trailing
underscore completely. I think 'deprecation' is what misguided us of
your intentions here. Deprecating something which is as unspecified as
the poor panda twins makes only little sense because no one could have
seriously relied on that feature (though reality will teach me
otherwise probably). Couldn't we just add an error message in the
overloaded case which says "Ambiguous reference to overloaded method
`foo` in partial application, add an explicit type ascription to
disambiguate." or something more glorious?

--
Johannes

-----------------------------------------------
Johannes Rudolph
http://virtual-void.net

martin odersky

unread,
Apr 4, 2011, 5:08:09 AM4/4/11
to scala-l...@googlegroups.com, Johannes Rudolph, Jason Zaugg, Chris Twiner
On Mon, Apr 4, 2011 at 10:43 AM, Johannes Rudolph <johannes...@googlemail.com> wrote:
On Mon, Apr 4, 2011 at 10:11 AM, Jason Zaugg <jza...@gmail.com> wrote:
> For the record, I'm only advocating a deprecation in the case of an
> overloaded panda. Who is probably already sad.

Good to know! I wouldn't be too happy as well to lose the trailing
underscore completely. I think 'deprecation' is what misguided us of
your intentions here. Deprecating something which is as unspecified as
the poor panda twins makes only little sense because no one could have
seriously relied on that feature (though reality will teach me
otherwise probably). Couldn't we just add an error message in the
overloaded case which says "Ambiguous reference to overloaded method
`foo` in partial application, add an explicit type ascription to
disambiguate." or something more glorious?

I'm more radical than Jason: I'd like to deprecate trailing _ (but that's a wish, not a plan). Also, if at some point we manage to unify tupled and n-ary functions, then 
f _ is exactly the same as f(_). At that time we should deprecate. Again, nothing like that is planned yet. There are too many more urgent things to do.

Cheers

 -- Martin




Johannes

-----------------------------------------------
Johannes Rudolph
http://virtual-void.net



--
----------------------------------------------
Martin Odersky
Prof., EPFL and CEO, Scala Solutions
PSED, 1015 Lausanne, Switzerland


Jason Zaugg

unread,
Apr 4, 2011, 5:30:35 AM4/4/11
to Johannes Rudolph, scala-l...@googlegroups.com, Chris Twiner
On Mon, Apr 4, 2011 at 10:43 AM, Johannes Rudolph
<johannes...@googlemail.com> wrote:
> On Mon, Apr 4, 2011 at 10:11 AM, Jason Zaugg <jza...@gmail.com> wrote:
>> For the record, I'm only advocating a deprecation in the case of an
>> overloaded panda. Who is probably already sad.
>
> Good to know! I wouldn't be too happy as well to lose the trailing
> underscore completely. I think 'deprecation' is what misguided us of
> your intentions here. Deprecating something which is as unspecified as
> the poor panda twins makes only little sense because no one could have
> seriously relied on that feature (though reality will teach me
> otherwise probably). Couldn't we just add an error message in the
> overloaded case which says "Ambiguous reference to overloaded method
> `foo` in partial application, add an explicit type ascription to
> disambiguate." or something more glorious?

That would also suit me; I was suggesting deprecation as the more
conservative route.

I wouldn't actually bother to allow disambiguate through the the
expected type. I don't think pandering (ha!) to overloaders is worth
the baggage of spec and implementation complexity.

-jason

Reply all
Reply to author
Forward
0 new messages