2

The code:

object Link {

  //TYPE-1 (purely functional)
  def apply(name: String, target: Page, f: () => Unit, isExclusive: Boolean) = new Link(name, target, f, isExclusive)
  //..

  //TYPE-2 (purely side-effect)
  def apply(source: Page, target: Page, f: () => Unit, isExclusive: Boolean): Link = {
    val link = Link("LINK [" + source.getName + "]->[" + target.getName + "]", target, f, isExclusive)
    source += link
    link
  }

  //type-2 too
  def apply(source: Page, target: Page, isExclusive: Boolean): Link = Link (source, target, () => Unit, isExclusive)

}

The explanation: there are two types of apply methods - the type-1 simply returns what companion class constructor returns, and the type-2 does not return anything, instead it just does something with the new instance. Thus the two different sets of arguments for them. However, I get the error (see the bottom of the post) on the second type-2 apply method where the _Link_ is marked with the underscores:

  def apply(source: Page, target: Page, isExclusive: Boolean): Link = _Link_ (source, target, () => Unit, isExclusive)

The first type-2 apply method does some job and in the second (and 3rd and 4th...) type-2 apply methods I want to just refer to the first one, instead of duplicating what is written there. However, Scala-IDE does not allow me to do this unless all the apply methods of type-1 are commented out. Seems like that Scala-IDE gets lost among the signatures and can't see my obvious intent. Or am I doing something wrong?

The error: the second apply method shows an error which reads:

overloaded method value apply with alternatives: (source: org.app.Page,target: org.app.Page,f: () => Unit,isExclusive: Boolean)org.app.meta.Link < and> (name: String,target: org.app.Page,f: () => Unit,isExclusive: Boolean)org.app.meta.Link cannot be applied to (org.app.Page, org.app.Page, () => Unit.type, Boolean)

UPDATE

Please note that the type-1 apply method is called without problems from the first type-2 one.

noncom
  • 4,962
  • 3
  • 42
  • 70

2 Answers2

4

That looks like a bug in the Scala compiler (the error can be reproduced outside of Eclipse using scalac 2.9.2).

Check in the Scala issue tracker if this is a known issue (and open a ticket if needed).

Update

As explained by Harald Meland here, this is not a bug in the compiler.

Mirco Dotta
  • 1,300
  • 8
  • 13
  • thanks, but, omg, why are all these bug-tracking systems are pure hell when it comes to searching for something in them... I can't cope with the filter system and the mind-blowing amount of data it gives me on any search that I've tried... looks like there is no chance for me to tell whether this issue is known or not, and to which category exactly does this bug belong.. there are at least 3 compiler-related categories.. – noncom Jun 14 '12 at 16:13
  • Maybe send a message in the [scala-user ML](http://groups.google.com/group/scala-user) and ask if this is a known issue. Scala folks are pretty responsive there ;-) – Mirco Dotta Jun 14 '12 at 18:01
  • Yep, that is more acceptable for me, thanks again! I posted there, let's see what it brings... really this type of code is essential to the DSL I need to implement. – noncom Jun 15 '12 at 09:57
2

This is not a bug, check the error message in detail (the interesting part is boldface below) and you will see that the last apply method actually passes a function of wrong type signature, () => Unit.type and not simply () => Unit.

overloaded method value apply with alternatives: (source: org.app.Page,target: org.app.Page,f: () => Unit,isExclusive: Boolean)org.app.meta.Link < and> (name: String,target: org.app.Page,f: () => Unit,isExclusive: Boolean)org.app.meta.Link cannot be applied to (org.app.Page, org.app.Page, () => Unit.type, Boolean)

The reason is that there is only one value of type Unit, namely (), in your case however, when you call () => Unit in the last apply method, you are returning the companion object of type Unit and not its value.

To fix the error your getting, simply replace () => Unit with () => () in your last apply method.

It should then look like this:

def apply(source: Page, target: Page, isExclusive: Boolean): Link = Link (source, target, () => (), isExclusive)
Jakob Odersky
  • 1,371
  • 11
  • 23
  • Tricky! Ok, that works, *but* the other part of the question still remains: why does commenting out all the type-1 apply methods work also? (at least it compiles perfectly). Even when the wrong type signature of `() => Unit.type` is passed? – noncom Jun 15 '12 at 11:20
  • If there is only one candidate method, based on approximate types and arity, the arguments are typed according with an "expected" type of the corresponding formal parameter. Otherwise, they must be typed without an expected type, which means that the result type remains as `Unit.type`. stackoverflow.com/questions/2510108/why-avoid-method-overloading/2512001#2512001 – retronym Jun 16 '12 at 09:45