Pregunta

El uso de la librería de línea de comandos REPL:

def foo(x: Int): Unit = {}
def foo(x: String): Unit = {println(foo(2))}

da

error: type mismatch;
found: Int(2)
required: String

Parece que no se puede definir sobrecargado métodos recursivos en el REPL.Pensé que esto era un error en la Scala REPL y se presentó, pero fue casi al instante cerró con "wontfix:Yo no veo ninguna manera esto podría ser admitidos, dado que la semántica de la intérprete, ya que estos dos métodos deben ser compilados juntos." Se recomienda poner los métodos en un adjuntando objeto.

Hay una JVM implementación del lenguaje o de la Scala de expertos que podría explicar por qué?Puedo ver sería un problema si los métodos se llamaban unos a otros, por ejemplo, pero en este caso?

O si esta es demasiado grande una pregunta y creo que necesitan más conocimientos previos, ¿alguien tiene alguna buena enlaces a libros o sitios acerca de las implementaciones de lenguajes, especialmente en la JVM?(Yo sé acerca de Juan de la Rosa del blog, y el libro de Lenguaje de Programación Pragmática...pero de eso se trata.:)

¿Fue útil?

Solución

El problema es debido al hecho de que el intérprete de la mayoría de los casos a reemplazar los elementos existentes con un nombre dado, en lugar de la sobrecarga de ellos.Por ejemplo, voy a menudo se ejecuta a través de la experimentación con algo, a menudo la creación de un método llamado test:

def test(x: Int) = x + x

Un poco más tarde, digamos que estoy corriendo un diferentes experimento y me cree otro método denominado test, ajenas a la primera:

def test(ls: List[Int]) = (0 /: ls) { _ + _ }

Esto no es un realista escenario.De hecho, es precisamente cómo la mayoría de la gente usa un intérprete, a menudo sin ni siquiera darse cuenta de ello.Si el intérprete arbitrariamente decidió mantener ambas versiones de test en el ámbito de aplicación, que podría llevar a confundir las diferencias de semántica en el uso de la prueba.Por ejemplo, podríamos hacer una llamada a test, accidentalmente , pasando de un Int en lugar de List[Int] (no es el más raro de accidentes en el mundo):

test(1 :: Nil)  // => 1
test(2)         // => 4  (expecting 2)

A lo largo del tiempo, en el ámbito raíz de la intérprete podría conseguir muy desordenado con varias versiones de los métodos, campos, etc.Que tienden a dejar mi intérprete abierto durante días a la vez, pero si la sobrecarga de este tipo fueron permitidos, nos veríamos obligados a "ras" de la intérprete de cada tan a menudo como la situación llegó a ser demasiado confuso.

No es una limitación de la JVM o el compilador de Scala, es una deliberada decisión de diseño.Como se mencionó en el error, usted todavía puede sobrecarga si está dentro de algo distinto de la raíz alcance.Adjuntando los métodos de prueba dentro de una clase parece que la mejor solución para mí.

Otros consejos

% scala28
Welcome to Scala version 2.8.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def foo(x: Int): Unit = () ; def foo(x: String): Unit = { println(foo(2)) } 
foo: (x: String)Unit <and> (x: Int)Unit
foo: (x: String)Unit <and> (x: Int)Unit

scala> foo(5)

scala> foo("abc")
()

REPL aceptará si se copian las líneas y pegar ambos al mismo tiempo.

Como se muestra por extempore del respuesta, es posible sobrecarga. Daniel comentario acerca de la decisión de diseño es correcto, pero, creo, incompleta y un poco engañoso.No hay la ilegalización de de sobrecargas (ya que también es posible), pero que no se consiguen fácilmente.

Las decisiones de diseño que llevan a esto son:

  1. Todas las definiciones anteriores deben estar disponibles.
  2. Sólo recién entrado el código es compilado, en lugar de volver a compilar todo lo que alguna vez entró en cada momento.
  3. Debe ser posible redefinir las definiciones (como Daniel mencionado).
  4. Debe ser posible definir los miembros como el vals y defs, no sólo las clases y los objetos.

El problema es...cómo lograr todos estos objetivos?¿Cómo podemos procesar su ejemplo?

def foo(x: Int): Unit = {}
def foo(x: String): Unit = {println(foo(2))}

Comenzando con el 4to elemento, Un val o def sólo puede ser definido dentro de un class, trait, object o package object.Así, REPL pone las definiciones en el interior de los objetos, como este (no representación real!)

package $line1 { // input line
  object $read { // what was read
    object $iw { // definitions
      def foo(x: Int): Unit = {}
    }
    // val res1 would be here somewhere if this was an expression
  }
}

Ahora, debido a la forma de JVM obras, una vez que haya definido uno de ellos, no se puede extender a ellos.Usted podría, por supuesto, volver a compilar todo, pero hemos descartado que.Por lo que necesita para colocarlo en un lugar diferente:

package $line1 { // input line
  object $read { // what was read
    object $iw { // definitions
      def foo(x: String): Unit = { println(foo(2)) }
    }
  }
}

Y esto explica por qué tus ejemplos no son sobrecargas:se definen en dos lugares diferentes.Si se les pone en la misma línea, todos ellos tendrían que ser definidas en conjunto, lo que los haría sobrecargas, como se muestra en la extempore del ejemplo.

Como para las otras decisiones de diseño, cada nuevo paquete de importación de definiciones y "res" de los paquetes anteriores, y las importaciones de sombra unos a otros, lo que hace posible para "redefinir" las cosas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top