Toda esta charla sobre la función recursiva y el tipo es una pista falsa. La gramática de Scala no permite operadores de postfix en ningún otro lugar que no sea el final de una expresión. Esta es la gramática de la que estamos hablando: la sintaxis de las cosas sin ninguna semántica. Aquí está la gramática relevante de las especificaciones:
Expr ::= (Bindings | [‘implicit’] id | ‘_’) ‘=>’ Expr
| Expr1
Expr1 ::= ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[semi] else Expr]
| ‘while’ ‘(’ Expr ‘)’ {nl} Expr
| ‘try’ ‘{’ Block ‘}’ [‘catch’ ‘{’ CaseClauses ‘}’]
[‘finally’ Expr]
| ‘do’ Expr [semi] ‘while’ ‘(’ Expr ’)’
| ‘for’ (‘(’ Enumerators ‘)’ | ‘{’ Enumerators ‘}’)
| {nl} [‘yield’] Expr
| ‘throw’ Expr
| ‘return’ [Expr]
| [SimpleExpr ‘.’] id ‘=’ Expr
| SimpleExpr1 ArgumentExprs ‘=’ Expr
| PostfixExpr
| PostfixExpr Ascription
| PostfixExpr ‘match’ ‘{’ CaseClauses ‘}’
PostfixExpr ::= InfixExpr [id [nl]]
Los únicos dos lugares en los que aparece al lado de PostfixExpr
éstos son después de la if
en un comunicado case
y antes : _*
en una lista de argumentos. Entonces, mirando eso, vemos que las únicas cosas que pueden aparecer en el lado derecho del nombre de método de una expresión de postfix es una adscripción de tipo match
.
Entonces, ¿qué expresiones finales? Bueno, las expresiones aparecen en muchos lugares de la gramática, por lo que hay muchas cosas que podrían ponerle fin. En este ejemplo particular, la expresión es BlockStat
dentro de un Block
, por lo que debe terminar con un punto y coma, que se puede inferir o no.
Para inferir este punto y coma, es necesario que la siguiente línea no sea algo que se pueda analizar como otro tipo de expresión. En este caso particular, tenemos esto:
val aFact = a!
println("factorial of " + a + " is " + aFact)
Ahora, vamos a reescribir que desde el punto de vista del compilador:
val id = id id
id (stringLit id id id stringLit id id)
Estos literales e identificadores se analizan como sigue:
val id = id id id (expr)
val Pattern2 = SimpleExpr1 id SimpleExpr1 ArgumentExprs
val Pattern2 = InfixExpr
val Pattern2 = Expr
val PatDef
PatVarDef
Def
BlockStat
Así que parece una expresión de infijo válida para el compilador mientras analiza su programa. Después, notó que los tipos no coincidían, pero es demasiado tarde para volver atrás y ver si se puede inferir un punto y coma.
posible duplicado de [¿Por qué la inferencia de punto y coma de Scala falla aquí?] (Http://stackoverflow.com/questions/2246212/why-does-scalas-semicolon-inference-fail-here) – missingfaktor
Factor de @Missing: I don No creo que sea la misma pregunta.Tanto la pregunta es sobre la inferencia del tipo de error, pero aquí tengo un operador unario y una conversión implícita (y no entiendo por qué eliminaste la etiqueta de inferencia de tipo) – onof
@onof: el compilador no sabe que es un operador unario. Para el compilador, es solo un método normal. La pregunta es básicamente la misma: "¿por qué la inferencia de punto y coma falla para esta llamada a método en notación de sufijo?". – missingfaktor