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

这些行是什么意思(Scala/JavaTokenParser)?,scala,parsing,Scala,Parsing,我试图更好地理解如何进行大规模解析/解释 我很难理解这样的句子: type L = () => Long 然后还有其他的线路,比如 val term = chainl1(myNum, "[*/]".r ^^ { case "*" => (u1:L, u2:L) => () => u1() * u2() case "/" => (u1:L, u2:L) => () => u1() / u2() }) 我只是想了解这里的基本结构。这里到底是什么?

我试图更好地理解如何进行大规模解析/解释

我很难理解这样的句子:

type L = () => Long
然后还有其他的线路,比如

val term = chainl1(myNum, "[*/]".r ^^ {
  case "*" => (u1:L, u2:L) => () => u1() * u2()
  case "/" => (u1:L, u2:L) => () => u1() / u2()
})
我只是想了解这里的基本结构。这里到底是什么?这些val语句的逻辑流程是什么

我假设这意味着如果我们在myNum中找到*或/的话,根据它是哪一个匹配这两种情况,然后。。。我不明白逻辑的长河

type L = () => Long
描述一个参数为零且返回类型为Long的函数。比如说

def someConstant() = 5L
这里有一个常数是L型的

这条线

case "*" => (u1:L, u2:L) => () => u1() * u2()
将返回Function2 arity 2类型的函数,返回类型为Function0arity 0,调用该函数时将返回u1*u2的结果

val f=>x:Int=>x

可以写成

=>x:Int=>x

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

 f()(6) == 6
这句话是真的

描述一个参数为零且返回类型为Long的函数。比如说

def someConstant() = 5L
这里有一个常数是L型的

这条线

case "*" => (u1:L, u2:L) => () => u1() * u2()
将返回Function2 arity 2类型的函数,返回类型为Function0arity 0,调用该函数时将返回u1*u2的结果

val f=>x:Int=>x

可以写成

=>x:Int=>x

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

 f()(6) == 6

是true语句。

ka4ell的答案是正确的,但没有说明为什么要使用=>Long而不是Long:with=>Long或L返回Long的计算的执行被延迟。我们只在需要实际结果的时候执行函数,这称为延迟求值

就你而言:

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的简单函数:

如果我们使用一个类似的函数,而不是本例中的函数:

// 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

ka4ell的答案是正确的,但是没有提到为什么要使用=>Long而不是Long:with=>Long或L返回Long的计算的执行被延迟。我们只在需要实际结果的时候执行函数,这称为延迟求值

就你而言:

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的简单函数:

如果我们使用一个类似的函数,而不是本例中的函数:

// 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
如果我们拆分行case*=>u1:L,u2:L=>=>u1*u2:

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

u1:L,u2:L=>{}是具有两个L类型参数的函数的定义

u1和u2是函数,因为它们的类型是L,它实际上是=>Long,这意味着这是一个不接受任何内容并返回Long的函数

=>u1*u2是一个没有参数的函数,它调用u1和u2并将其结果相乘 往回看: u1:L,u2:L=>=>u1*u2是一个有两个参数的函数,它返回一个没有参数的函数,它执行第一个函数的两个参数,将它们相乘并返回结果

因此,=>表示一个没有参数的函数。这里唯一的例外是case*=>where=>不属于函数,而是匹配语句

如果我们拆分case*=>u1:L,u2:L=>=>u1*u2:

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

u1:L,u2:L=>{}是具有两个L类型参数的函数的定义

u1和u2是函数,因为它们的类型是L,它实际上是=>Long,这意味着这是一个不接受任何内容并返回Long的函数

=>u1*u2是一个没有参数的函数,它调用u1和u2并将其结果相乘 往回看: u1:L,u2:L=>=>u1*u2是一个有两个参数的函数,它返回一个没有参数的函数,它执行第一个函数的两个参数,将它们相乘并返回结果

因此,=>表示一个没有参数的函数。这里唯一的例外是case*=>where=>

不属于函数,而是匹配语句

那么像case*=>u1:L,u2:L=>=>u1*u2这样的行是什么意思呢?我还是不太明白。上面写着case*然后以某种方式提取了两个数字——是说u1和u2必须是L型的,还是它们被转换成L型的?那为什么会有额外的=>=>部分呢?为什么要使用u1和u2?如果您正在使用scala,那么您可以通过查看代码示例来学习scala语言。你需要阅读一本书,浏览教程等。它的结构往往比这复杂得多,如果你不准备,你就会迷失在那里yourself@Archeg我通过榜样学习得最好。阅读抽象教程和书籍对我没有任何帮助。我需要很难的例子来理解事物是如何组合起来的。我可以在事后找出抽象的概念,它不提取两个数字。在*的情况下,它返回一个接受两个类型为L的参数的函数。需要调用此函数来执行任何操作,并且需要传递两个类型为L的值,这两个值本身就是函数。所以这个例子返回一个函数,它接受两个函数,并提供一个Long类型的结果。那么像case*=>u1:L,u2:L=>=>u1*u2这样的行是什么意思呢?我还是不太明白。上面写着case*然后以某种方式提取了两个数字——是说u1和u2必须是L型的,还是它们被转换成L型的?那为什么会有额外的=>=>部分呢?为什么要使用u1和u2?如果您正在使用scala,那么您可以通过查看代码示例来学习scala语言。你需要阅读一本书,浏览教程等。它的结构往往比这复杂得多,如果你不准备,你就会迷失在那里yourself@Archeg我通过榜样学习得最好。阅读抽象教程和书籍对我没有任何帮助。我需要很难的例子来理解事物是如何组合起来的。我可以在事后找出抽象的概念,它不提取两个数字。在*的情况下,它返回一个接受两个类型为L的参数的函数。需要调用此函数来执行任何操作,并且需要传递两个类型为L的值,这两个值本身就是函数。所以这个例子返回一个函数,它接受两个函数,并提供一个Long类型的结果。我尝试用其他任意字母(如X)替换L,以查看这是否是一个一般性的问题,它给了我错误。这整件事只对长时间有效吗?我是某种本地类型的缩写吗?当我从5和2中删除L时,它似乎也执行了。我仍在努力理解heck类型L==>Long在做什么以及为什么我们想要它我只是使用了类型L,因为这是您使用的,它不是本机类型。尝试用另一个像X这样的字母替换L,它突然停止工作:val productX=multiplygiveMeAnX5X,giveMeAnX2X//无效的文字数字5L和2L后面的L是一个不吉利的结果。它在没有L的情况下工作,因为这里的5和2整数变成了长整数,所以在一个数字后面加一个L是Scala固有的,与这个问题无关?它将其类型转换为Long,但这是不必要的,因为这是在调用giveMeAnX时自动完成的,因为参数类型为n:Long?我尝试用其他任意字母(如X)替换L,以查看这是否是一个一般性的问题,它给了我错误。这整件事只对长时间有效吗?我是某种本地类型的缩写吗?当我从5和2中删除L时,它似乎也执行了。我仍在努力理解heck类型L==>Long在做什么以及为什么我们想要它我只是使用了类型L,因为这是您使用的,它不是本机类型。尝试用另一个像X这样的字母替换L,它突然停止工作:val productX=multiplygiveMeAnX5X,giveMeAnX2X//无效的文字数字5L和2L后面的L是一个不吉利的结果。它在没有L的情况下工作,因为这里的5和2整数变成了长整数,所以在一个数字后面加一个L是Scala固有的,与这个问题无关?它将其类型转换为Long,但这是不必要的,因为这是在调用giveMeAnX时自动完成的,因为参数类型n:Long?我想对我来说,主要的问题是一个不接受参数的函数突然分支成似乎接受参数的函数。例如,我不明白我们如何从u1和u2开始。u1和u2不是参数吗?这里似乎有些不必要的复杂。我们有一个函数定义,两个函数返回一个无参数函数,返回两个函数的乘法器,对应于一个类型,该类型不返回参数函数,产生long?什么?u1和u2是父函数的参数。子函数只是在它们周围有闭包。举个小例子,假设L=Int。假设您有val parentF=u1:L,u2:L=>=>u1*u2。然后取val childF=parentF2,3。childF仍然是一个函数,但它没有参数。现在看起来有点像=>2*3,这不精确,但我认为这有助于
顶住它。这里发生的事情是,childFunction在创建时,记住了对u1和u2的引用,这种行为称为闭包。请记住,L==>Long in realitySo childFunction是一个不接受任何参数的函数,因为在我们进行赋值时,这些参数已经封装在parentF中了?现在,每当我们处理childF时,我们都会隐式地处理parentF2,3,也就是说,childF引用parentF2,3,这里有两个参数2,3是很好的,因为parentF是形式为u1:Int,u2:Int的函数,它返回一个函数,当调用该函数时,它将乘以u1和u2。现在如果我输出childF,它将输出6?我理解流了吗?childFunction是一个不接受任何参数的函数,因为它是用=>。。。但它实际上需要u1和u2,没有它们就无法工作。它被称为闭包,因为如果我正确地提到了这个术语,一个需要u1和u2但没有它们的函数被称为opened。所以它是通过有一个包含u1和u2的父函数来关闭的。我仍然建议你开始读一本书:看看你所引发的讨论的规模,我想主要的问题是一个不接受参数的函数突然分支成了一个似乎接受参数的函数。例如,我不明白我们如何从u1和u2开始。u1和u2不是参数吗?这里似乎有些不必要的复杂。我们有一个函数定义,两个函数返回一个无参数函数,返回两个函数的乘法器,对应于一个类型,该类型不返回参数函数,产生long?什么?u1和u2是父函数的参数。子函数只是在它们周围有闭包。举个小例子,假设L=Int。假设您有val parentF=u1:L,u2:L=>=>u1*u2。然后取val childF=parentF2,3。childF仍然是一个函数,但它没有参数。现在看起来有点像=>2*3,这并不精确,但我认为这有助于理解它。这里发生的事情是,childFunction在创建时,记住了对u1和u2的引用,这种行为称为闭包。请记住,L==>Long in realitySo childFunction是一个不接受任何参数的函数,因为在我们进行赋值时,这些参数已经封装在parentF中了?现在,每当我们处理childF时,我们都会隐式地处理parentF2,3,也就是说,childF引用parentF2,3,这里有两个参数2,3是很好的,因为parentF是形式为u1:Int,u2:Int的函数,它返回一个函数,当调用该函数时,它将乘以u1和u2。现在如果我输出childF,它将输出6?我理解流了吗?childFunction是一个不接受任何参数的函数,因为它是用=>。。。但它实际上需要u1和u2,没有它们就无法工作。它被称为闭包,因为如果我正确地提到了这个术语,一个需要u1和u2但没有它们的函数被称为opened。所以它是通过有一个包含u1和u2的父函数来关闭的。我仍然建议你开始读一本书:看看你引发的讨论的规模