2010-02-11 11 views
16

Al compilar el código siguiente con Scala 2.7.3,¿Por qué la inferencia de punto y coma de Scala falla aquí?

package spoj 

object Prime1 { 
    def main(args: Array[String]) { 
    def isPrime(n: Int) = (n != 1) && (2 to n/2 forall (n % _ != 0)) 
    val read = new java.util.Scanner(System.in) 
    var nTests = read nextInt // [*] 
    while(nTests > 0) { 
     val (start, end) = (read nextInt, read nextInt) 
     start to end filter(isPrime(_)) foreach println 
     println 
     nTests -= 1 
    } 
    } 
} 

me sale el siguiente error de tiempo de compilación:

PRIME1.scala:8: error: illegal start of simple expression 
    while(nTests > 0) { 
    ^
PRIME1.scala:14: error: block must end in result expression, not in definition 
    } 
^
two errors found 

Cuando agrego un punto y coma al final de la línea comentada como [*], el programa compila bien ¿Puede alguien explicar por qué la inferencia de punto y coma de Scala no funciona en esa línea en particular?

+1

Justo fuera del tema, '2 a n/2' se puede reemplazar por' 2 en Math.sqrt (n) '- es la solución canónica, aunque no sé si proporcionará un mejor rendimiento (Creo que no) – incarnate

+0

sé que este es un hilo VIEJO, pero ¿podría poner explícitamente el punto y coma después de la línea 'read nextInt'? ¿o es un problema porque no se proporciona ningún argumento para 'nextInt'? – Ramy

+0

@Ramy: Lee las respuestas. – missingfaktor

Respuesta

19

Es porque scala está asumiendo que está utilizando la sintaxis a foo b (equivalente a a.foo(b)) en su llamada al readInt. Es decir, se asume que el bucle while es el argumento para readInt (recordemos que cada expresión tiene un tipo) y por lo tanto la última afirmación es una declaración:

var ntests = read nextInt x 

donde x es su bloque de tiempo.

hay que decir que, como punto de preferencia, ahora he vuelto a usar la sintaxis habitual a.foo(b) sobre a foo ba no ser que el trabajo específico con una conexión DSL que fue diseñado con ese fin en mente (como actores a ! b) . ¡Hace las cosas mucho más claras en general y no te pican por cosas raras como esta!

+4

+1 por la recomendación en el último párrafo – ziggystar

+0

Sé que este es un hilo VIEJO, pero ¿podría poner explícitamente el punto y coma después de leer la línea nextInt? o ¿es esto un problema porque no se proporciona ningún argumento a nextInt? – Ramy

11

comentario adicional a la respuesta por oxbow_lakes ...

var ntests = read nextInt() 

En caso de arreglar las cosas para usted como una alternativa a la del punto y coma

8

Para añadir un poco más sobre la inferencia de punto y coma, Scala realmente hace esto en dos etapas Primero infiere un token especial llamado nl por la especificación de idioma. El analizador permite usar nl como un separador de instrucciones, así como puntos y comas. Sin embargo, nl también está permitido en algunos otros lugares por la gramática. En particular, se permite un solo nl después de los operadores de infijo cuando el primer token en la línea siguiente puede iniciar una expresión, y while puede iniciar una expresión, por lo que lo interpreta de esa manera. Desafortunadamente, aunque while puede iniciar una expresión, una instrucción while no se puede usar en una expresión infija, de ahí el error. Personalmente, parece una forma bastante peculiar para que el analizador funcione, ¡pero, por lo que sé, hay bastante razón lógica detrás de esto!

Como otra opción para los otros sugirieron, poniendo una nueva línea en blanco entre su línea [*] y la línea while también se solucionará el problema, ya que sólo una sola nl se permite después de operadores infijos, de modo múltiple nl s fuerza una interpretación diferente por el analizador.

Cuestiones relacionadas