def or val or lazy val for grammar rules?

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-10 16:26:53

问题


I know the difference between def and val and lazy val in general, but I'm not sure about their repercussions when it comes to Parser Combinators. All examples I have seen contain code like this:

def statement: Parser[Statement] =
  ifStatement |
  whileStatement |
  expressionStatement | ...

From a few experiments I have done, it seems val and lazy val work as well, but I'm not sure if there are cases where they wouldn't work anymore, like recursion or positioned parsers or whatnot.

Please enlighten me!


回答1:


If you look at the api documentation, the parser-building methods and operators are implemented using by-name parameters which are then cached using lazy val.

That being said, you still have to be careful about order of initialization. The following code will result in a null reference exception:

val as = a.*
val a = "a"

However the following is fine (because the argument to ~ is by-name):

val as = "a" ~ a.*
val a = "a"

Putting lazy in front of everything will 'help', but is noisy. Performance should not be a big deal, as generally you will only want to initialize the grammar once. def expressions will be initialized once for each point they are referenced.

You can be a bit clever and eliminate plumbing for your 'minor' productions using block syntax:

lazy val addExpr = {
  val add = expr ~ "+" ~ expr
  val sub = expr ~ "-" ~ expr
  add | sub
}


来源:https://stackoverflow.com/questions/19188964/def-or-val-or-lazy-val-for-grammar-rules

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!