Domanda

Sto lavorando su un DSL e ho riscontrato un problema con l'utilizzo di metodi come operatori infissi in una catena.Cercherò solo di spiegarlo con un po 'di codice.Ho un tratto Term e classi case Literal e Variable che lo estendono.Voglio costruire un elenco di istanze di termini utilizzando alcuni operatori.

case class Expr(val terms: List[Term]) {
 def +(v: String) = Expr(Literal(v) :: terms)
 def -->(func: List[String] => List[String]) = terms match {
  case Literal(v) :: ts => Expr(Variable(v, func) :: ts)
  case _ => throw new Exception("Can only apply function on literal")
 }
}

object foo {
 def bar(name: String) = Expr(Literal(name) :: Nil)
}

// some functions
val one = ... 
val all = ...

// works
foo bar "x"        
// res1: Expr = Expr(List(Literal(x)))

// works not
foo bar "x" --> all
// error: value --> is not a member of java.lang.String

// works
(foo bar "x") --> all 
// res1: Expr = Expr(List(Variable(x,<function1>)))

Mi aspetterei che questo sarebbe equivalente a foo.bar("x").-->(all) ma l'interprete sembra vederlo come foo.bar("x".-->(all)).

È stato utile?

Soluzione

Puoi trovare la precedenza degli operatori qui:

Precedenza degli operatori in Scala

Secondo la prima risposta - ha una priorità maggiore rispetto alle lettere.Quindi il compilatore raggruppa espressioni come questa:

foo bar ("x" --> all)

Se sostituirai --> con qualcosa di priorità inferiore (ad esempio lettere), allora dovrebbe essere compilato.Ad esempio:

foo bar "x" to all

Puoi anche scegliere un operatore con priorità più alta invece di bar.Qualcosa come ~~> lo farà, perché ~ è un carattere speciale e ha la massima priorità:

foo ~~> "x" --> all
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top