V meste Scaladoc RegexParsers, je nasledujúci kód:
object Calculator extends RegexParsers {
def number: Parser[Double] = """d+(.d*)?""".r ^^ { _.toDouble }
def factor: Parser[Double] = number | "(" ~> expr <~ ")"
...
Nevidím, prečo sme to napísali s def
a nie s val
alebo a lazy val
? Napíšem takto:
object Calculator extends RegexParsers {
lazy val number: Parser[Double] = """d+(.d*)?""".r ^^ { _.toDouble }
lazy val factor: Parser[Double] = number | "(" ~> expr <~ ")"
...
odpovede:
1 pre odpoveď č. 1Existuje skutočný sémantický dôvod. Pozrite sa na typový podpis pre Parser
:
abstract class Parser[+T] extends (Input) ⇒ ParseResult[T]
Parser[T]
je v skutočnosti funkciou z nejakého abstraktného druhu Input
na a ParseResult[T]
, V mnohých (pravdepodobne väčšine) prípadoch táto funkcia zachycuje niektoré aspekty stavu vyšetrovania. Ak bola takáto produkcia zachytená v a val
, (lenivý alebo inak) nemohol byť použitý na viac ako jednom mieste v danom parse stromu. Jediné produkcie, ktoré je možné vyrobiť val
sú pevné terminály, ako napríklad interpunkcia a kľúčové slová.
dodatky
Už niekoľko rokov som pracoval na Scalekombinátor parserov a bol som v tom čase pomerne Scala nováčik, takže je úplne možné, že som sa jednoducho mýlil, ale moja spomienka je, že Reader
nereprezentoval vstup ako celok, ale skôr špecifickú subsekvenciu tohto vstupu. Ak teda výroba nemala pevnú vstupnú sekvenciu, produkcia by nemala byť a val
.
Vlastne mám malý bočný projekt, ktorý potrebuje analyzátora, takže keď dostanem nejaký čas, môžem toto porozumenie potvrdiť alebo vyvrátiť.