2011-05-25 34 views
8

Scala Novato ... estoy confundidoScala matrices vs vectores

object myApp extends App { 
    println("Echo" + (args mkString " ")) 
} 

"args" es de tipo Array [String], pero en el scaladoc, Array no tiene tal método. mkString es un método para Vector, pero no veo ningún vínculo de herencia entre los dos. Entonces, ¿por qué podemos usar el método mkString en args?

Respuesta

16

No soy un experto en scala (¡lejos de eso!) Pero creo que la respuesta son las conversiones implícitas (ver scala.Predef) y WrappedArray.scala.

En particular, Predef tiene la siguiente conversión implícita:

implicit def genericWrapArray [T] (xs: Array[T]): WrappedArray[T] 

Y WrappedArray tiene un método mkString. Cuando Scala no puede encontrar un método mkString en Array, busca una conversión implícita a un tipo que sí lo haga.

http://www.scala-lang.org/api/current/scala/Predef $ .html

http://www.scala-lang.org/api/current/scala/collection/mutable/WrappedArray.html

+2

Gracias, no tuve cabeza de conversiones implícitas. WrappedArray y Vector obtienen el método mkString del rasgo TraversableOnce que comparten. ¿Podría ser útil si Scaladoc te dijera en una definición de clase qué definiciones implícitas existían? –

12

Ampliando la respuesta de Kevin y explicar por qué no es posible para scaladoc de decirle lo que existe la conversión implícita: las conversiones implícitas sólo entran en juego cuando el código no lo haría compila lo contrario.

Puede verlo como un mecanismo de recuperación de error para errores de tipo que se activa durante la compilación. En este caso, Array[String] no tiene un método mkString. Este código no se compilaría porque ese método no existe en Array[T]. Pero antes de renunciar, el compilador buscará una conversión implícita en el alcance.

Ocurre que Predef trae un número de conversiones implícitas en el alcance y una que se aplicará aquí.

Averiguar qué conversión implícita se aplica se puede hacer mediante la compilación con el -Xprint:typer marca. En este caso, sería imprimir:

$ scalac -d classes -Xprint:typer A.scala 
[[syntax trees at end of typer]]// Scala source: A.scala 
package <empty> { 
    final object myApp extends java.lang.Object with App with ScalaObject { 
    def this(): object myApp = { 
     myApp.super.this(); 
    () 
    }; 
    scala.this.Predef.println("Echo ".+(scala.this.Predef.refArrayOps[String](myApp.this.args).mkString(" "))) 
    } 
} 

Así se puede ver que Predef.refArrayOps es, de hecho, la conversión implícita utiliza. Convierte tu matriz en ArrayOps[String] que tiene un mkString method.

Así que con eso en mente, usted puede ver por qué scaladoc para Array no puede decir lo que se podría aplicar la conversión implícita. Podría ser cualquier cosa. De hecho, se basa completamente en el hecho de que no existe tal método. Solo el compilador sabrá qué implícito encontró en función del código.

Incluso puede definir su propia conversión implícita:

object myApp extends App { 
    implicit def myImplicit(arr:Array[String]) = new { 
    def mkString(s:String) = arr.length + s 
    } 
    println("Echo " + (args mkString(" "))) 
} 

que tendría el siguiente efecto:

$ scala -cp classes myApp a b c 
Echo 3 

Obviamente scaladoc no será capaz de demostrar que. Tenga en cuenta que el complemento Eclipse Scala puede llevarlo a la implementación de mkString presionando F3 (terminará en TraversableOnce).

+0

Gracias por la explicación detallada :) –

2

Pero Scaladoc podría al menos decir que Predef (que es especial porque siempre está dentro del alcance) tiene una conversión implícita de Array. Eso sería útil.