Details

      Description

      It is not possible to overload applyDynamic because the name parameter is required to be by itself in the first parameter list:

      import language.dynamics
      
      object J {
         val x = new X(3)
      
         x.call(3,9)
      
         class X(i: Int) extends Dynamic {
            def applyDynamic(name: String)(in: Int): Int = i + in
            def applyDynamic(name: String)(a: Int, b: Int): Int = a + b
         }
      }
      
      J.scala:6: error: ambiguous reference to overloaded definition,
      both method applyDynamic in class X of type (name: String)(a: Int, b: Int)Int
      and  method applyDynamic in class X of type (name: String)(in: Int)Int
      match argument types (String)
         x.call(3,9)
         ^
      

        Issue Links

          Activity

          Hide
          Paul Phillips added a comment -

          Going to revert the implementation restriction, because I thought of this, which does work given explicit type application:

          import scala.language.dynamics
          
          class A extends Dynamic {
            def applyDynamic[T1](method: String)(x1: T1): Any = 1
            def applyDynamic[T1, T2](method: String)(x: T1, y: T2): Any = 2
          }
          
          object Test {
            def main(args: Array[String]): Unit = {
              val x = new A
              println(x[Int](5))
              println(x[Int, String](5, "a"))
            }
          }
          

          However, I hope this causes people reconsider whether the overloading-hostile structure of applyDynamic makes sense. I think this shows that it does not. With no way to express a variable-length type parameter list, we have again, following in the footsteps of structural types, created a pseudo-general mechanism which is incapable by design of being used in common situations for which it would otherwise be useful, creating unnecessary surprises and friction. There is no way to write a dynamic method which can receive every application of a method name. You could push the above out to N type parameters, but then there's no way to avoid explicit type application.

          Show
          Paul Phillips added a comment - Going to revert the implementation restriction, because I thought of this, which does work given explicit type application: import scala.language.dynamics class A extends Dynamic { def applyDynamic[T1](method: String)(x1: T1): Any = 1 def applyDynamic[T1, T2](method: String)(x: T1, y: T2): Any = 2 } object Test { def main(args: Array[String]): Unit = { val x = new A println(x[Int](5)) println(x[Int, String](5, "a")) } } However, I hope this causes people reconsider whether the overloading-hostile structure of applyDynamic makes sense. I think this shows that it does not. With no way to express a variable-length type parameter list, we have again, following in the footsteps of structural types, created a pseudo-general mechanism which is incapable by design of being used in common situations for which it would otherwise be useful, creating unnecessary surprises and friction. There is no way to write a dynamic method which can receive every application of a method name. You could push the above out to N type parameters, but then there's no way to avoid explicit type application.
          Hide
          Paul Phillips added a comment -

          See also SI-7059.

          Show
          Paul Phillips added a comment - See also SI-7059 .
          Hide
          Eugene Burmako added a comment -

          It looks like it's possible to overload applyDynamic using Paul's trick from SI-7059. The trick just needed a single small change!!

          02:00 ~/Projects/Master/sandbox (master)$ cat Test.scala
          import scala.language.dynamics
          
          class A extends Dynamic {
            def applyDynamic(method: String): B = new B(method)
          }
          class B(method: String) {
            def apply(x: Int) = s"$method(x: Int)"
            def apply(x: String) = s"$method(x: String)"
          }
          
          object Test {
            def main(args: Array[String]): Unit = {
              val x = new A
              println(x.bippy(42))
              println(x.bippy("42"))
            }
          }
          
          02:00 ~/Projects/Master/sandbox (master)$ scalac Test.scala && scala Test
          bippy(x: Int)
          bippy(x: String)
          
          Show
          Eugene Burmako added a comment - It looks like it's possible to overload applyDynamic using Paul's trick from SI-7059 . The trick just needed a single small change!! 02:00 ~/Projects/Master/sandbox (master)$ cat Test.scala import scala.language.dynamics class A extends Dynamic { def applyDynamic(method: String): B = new B(method) } class B(method: String) { def apply(x: Int) = s"$method(x: Int)" def apply(x: String) = s"$method(x: String)" } object Test { def main(args: Array[String]): Unit = { val x = new A println(x.bippy(42)) println(x.bippy("42")) } } 02:00 ~/Projects/Master/sandbox (master)$ scalac Test.scala && scala Test bippy(x: Int) bippy(x: String)
          Hide
          Paul Phillips added a comment -

          Oh, nice job. That's some solid tunnel vision on my part.

          Show
          Paul Phillips added a comment - Oh, nice job. That's some solid tunnel vision on my part.
          Show
          Eugene Burmako added a comment - https://github.com/scala/scala/pull/3310

            People

            • Assignee:
              Eugene Burmako
              Reporter:
              Mark Harrah
            • Votes:
              0 Vote for this issue
              Watchers:
              8 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development