Scala: Gotchya!

I have been caught out by type-checking code that fails at runtime. It should have failed at compile-time due to a language limitation in structural types — not a logical absurdity in the code itself. Thankfully I have a workaround, but it does provoke persistent hesitance — giving that disgusting feeling as if I were using something as degenerate as, for example, Ruby or even worse (can it get worse?), Groovy. I’ll have to counsel myself on that one.

Nevertheless, I give warning. Here is the bug report. Here is the fun. Observe:

scala> def left[B] = new { def apply[A](a: A): Either[A, B] = Left(a) }
left: [B]java.lang.Object{def apply[A](A): Either[A,B]}
 
scala> left[String](7)
res6: Either[Int,String] = Left(7)
 
scala> def left[B] = new { def apply[A](a: A, b: B): Either[A, B] = Left(a) }
left: [B]java.lang.Object{def apply[A](A,B): Either[A,B]}
 
scala> left(7, "")
res8: Either[Int,java.lang.String] = Left(7)
 
scala> left[String](7, "")
java.lang.NoSuchMethodException: $anon$1.apply(java.lang.Object, java.lang.String)
        at java.lang.Class.getMethod(Class.java:1605)
        at .reflMethod$Method1(<console>:6)
        at .<init>(<console>:6)
        at .<clinit>(<console>)
        at RequestResult$.<init>(<console>:3)
        at RequestResult$.<clinit>(<console>)
        at RequestResult$result(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native ...

7 Responses to “Scala: Gotchya!”

  1. Paul King Says:

    An ignorant theoretician blames his languages.

  2. Tony Morris Says:

    Erm, in this case, an objective observer blames the language because it is a language limitation that is imposed as a limitation of the language that limits its usefulness by limiting the user. You can read all about it in the Scala Language Specification — 3.2.7 Compound Types.

    Nevertheless, this is a demonstrable fact that is irrefutable albeit the existence of cute cliché phrases (denoting more non-concepts! yay!). A logical absurdity cannot exist as a concept, regardless of the language (you’ll learn this one day I hope!) yet there exists a language where it is certainly possible to express this concept — quot est absurdum.

    This intellectual dishonesty is becoming ridiculous, not to mention its disgust.

  3. Jesper Nordenberg Says:

    Do you really want to use structural typing? The call performance sucks, and it’s very seldom needed. In the code you submitted in the bug report you can simply extend Function1 to avoid structural typing.

  4. Jesper Nordenberg Says:

    Hmm, the implicit parameter makes that impossible. I guess you could define a trait for functions that takes one normal and one implicit parameter.

  5. Paul King Says:

    “This intellectual dishonesty is becoming ridiculous”

    I guess you are referring to your comments on the differences between Groovy and Ruby here.

  6. Tony Morris Says:

    Hi Jesper, yes I have done exactly that — defined a trait where appropriate. It is most often when using higher-kinded type arguments that I desire their partial application.

  7. KindaFunny Says:

    Well Tony sometimes you make it difficult for other people to read you blog ;)
    Maybe you should point to the according source of your opinion , so other people could easier understand.
    Regarding that gotchya since Scala is WIP it’s actually good to see that such bugs are identified and addressed.

    Oh and another thing i recently read this:
    .http://jim-mcbeath.blogspot.com/2008/09/scala-syntax-primer.html#funcsugar
    And guess what!? In the lower part there is also a reference to :
    def compose[A, B, C](f: B => C, g: A => B): A => C = (a: A) => f(g(a))

    But if a nice ( trival easy to understand thats what we need, i mean it!) example:
    def plus1(n:Int):Int = n+1
    def intToParenString(n:Int) = “(”+n.toString+”)”
    val plus1string = compose(intToParenString,plus1)
    val x = plus1string(10) //this executes plus1 and intToParenString,
    //sets x to the string (11)

    I saw you presentation and the slides completly but somehow i’dont remember how that compose worked. After reading this:
    Note that executing the compose function does NOT execute functions f and g, but rather returns a function object which, when invoked, will execute f(g) on its argument.

    i could quite clearly see what it does and also why.

Leave a Reply