这些行是什么意思(Scala / JavaTokenParsers)?

时间:2015-07-17 13:45:54

标签: scala parsing

我正在努力更好地了解如何进行大规模解析/解释。

我很难理解这些行:

type L = () => Long

然后还有其他一些行,比如

val term = chainl1(myNum, "[*/]".r ^^ {
  case "*" => (u1:L, u2:L) => () => u1() * u2()
  case "/" => (u1:L, u2:L) => () => u1() / u2()
})

我只是想了解这里的基础结构。这里()究竟是什么?这些val语句的逻辑流程是什么?

我认为这意味着"如果我们在*中找到/myNum,则根据这两种情况匹配这两种情况,然后......长逻辑流程我不明白"

3 个答案:

答案 0 :(得分:4)

type L = () => Long

描述了一个零参数和返回类型为Long的函数。例如

def someConstant() = 5L

此处someConstant的类型为L

这一行

case "*" => (u1:L, u2:L) => () => u1() * u2()

将返回一个类型为Function2(arity 2)的函数,返回类型为Function0(arity 0),调用时将返回u1() * u2()的结果。

val f = () => (x:Int) => x

可以写成

() => ((x: Int) => x)

这里f是一个带有arity 0的函数,当调用when时,返回另一个arity 1函数,该函数接受Int参数并在调用时返回它。

 f()(6) == 6

是真实的陈述。

答案 1 :(得分:3)

ka4ell的答案是正确的,但没有提到为什么要使用() => Long而不是仅使用Long() => LongL执行计算返回Long的延迟。我们只在我们想要实际结果的时刻执行这些功能,这称为 lazy 评估。

在你的情况下:

case "*" => 
  // Return a function which takes two Ls : u1 and u2
  // and which returns an L : () => u1() * u2()
  (u1:L, u2:L) => () => u1() * u2()

让我们定义一个返回L的简单函数:

// return a function which will return a Long
// this could potentially be a very expensive calculation
def giveMeAnL(n: Long) = () => {
  println("giveMeAnL is called")
  n
}

如果我们使用的函数类似于案例中的函数:

// analogous case "*" => ...
def multiply(u1:L, u2:L) = () => {
  println("multiply is called")
  u1() * u2()
}

// create two Ls
val (l1, l2) = (giveMeAnL(5L), giveMeAnL(2L))

val productL = multiply(l1, l2) // productL is of type L

productL现在包含L,可以计算这两个值的乘积。此时,既不计算产品也不计算两个值。如果我们调用productL值,则会计算这两个值,并计算这些值的乘积。

val product = productL()
// multiply is called
// giveMeAnL is called
// giveMeAnL is called
// product: Long = 10

如果在解析步骤的某个位置,您想忽略某些L值,则永远不会计算这些L的结果,从而提高性能。

case "multiply first with 5" => 
  (u1:L, u2:L) => () => u1() * 5L // u2 is never executed

答案 2 :(得分:0)

如果我们拆分行case "*" => (u1:L, u2:L) => () => u1() * u2()

case "*" =>表示将*与下次编写的代码匹配

(u1:L, u2:L) => {}是函数的定义,它有两个类型为L

的参数

u1u2是函数,因为它们的类型是L,它实际上是() => Long,这意味着这是一个不带任何东西并返回{{1}的函数}}

Long是一个没有参数的函数,调用() => u1() * u2()u1并将其结果相乘 回去: u2是两个参数的函数,它返回一个无参数的函数,它执行第一个函数的两个参数,将它们相乘并返回结果

因此,(u1:L, u2:L) => () => u1() * u2()表示没有参数的函数。这里唯一的例外是() =>其中case * =>不属于某个函数,而是匹配语句