首页 > 其他分享 >5.3 Type inference 类型推断

5.3 Type inference 类型推断

时间:2025-01-05 10:44:20浏览次数:5  
标签:Term 5.3 inference 代码 --- LALRPOP bar Num Type

https://lalrpop.github.io/lalrpop/tutorial/003_type_inference.html

OK, now that we understand the calculator1 example, let's look at some of the shorthands that LALRPOP offers to make it more concise. This code is found in the calculator2 demo.

GPT --- 好的,现在我们理解了 calculator1 示例,让我们看看 LALRPOP 提供的一些简写方式,以使代码更加简洁。这些代码可以在 calculator2 示例中找到。

MST --- 好了,现在我们已经理解了 calculator1 示例,让我们看看 LALRPOP 提供的一些简写,以使其更简洁。此代码位于 calculator2 演示中。

To start, let's look at the definition of Term we saw before:

pub Term: i32 = {
    <n:Num> => n,
    "(" <t:Term> ")" => t,
};

The action code here is somewhat interesting. In both cases, it's not doing any new work, it's just selecting a value that was produced by another nonterminal. This turns out to be pretty common. So common, in fact, that LALRPOP offers some shorthand notation for it. Here is the definition of Term from the calculator2 demo:

GPT --- 这里的动作代码有些有趣。在这两种情况下,它并没有做任何新的工作,只是选择了由另一个非终结符生成的值。这实际上是非常常见的。所以,LALRPOP 提供了一些简写方式来处理这种情况。以下是 calculator2 示例中 Term 的定义:

MST --- 这里的操作代码有点有趣。在这两种情况下,它都没有做任何新工作,它只是选择由另一个非终端生成的值。事实证明这很常见。事实上,LALRPOP 为它提供了一些速记符号。以下是 calculator2 演示中 Term 的定义:

pub Term = { Num, "(" <Term> ")" };

Here, we have no action code at all. If there is no action code, LALRPOP synthesizes action code which just takes the value of the things being matched. In the case of the first alternative, Num, there is only one thing being matched, so that means that Term will produce the same value as the Num we parsed, whatever that was.

GPT --- 在这里,我们没有任何动作代码。如果没有动作代码,LALRPOP 会自动生成动作代码,默认情况下它会直接使用匹配到的值。在第一个替代定义 Num 的情况下,只有一个匹配项,这意味着 Term 将生成与我们解析的 Num 相同的值,无论那个值是什么。

MST --- 在这里,我们根本没有操作代码。如果没有操作代码,LALRPOP 会合成操作代码,该代码只接受被匹配内容的值。在第一个选项的情况下,Num 只有一个东西被匹配,所以这意味着 Term 将产生与我们解析的 Num 相同的值,无论它是什么。

In the case of the second alternative, "(" ")", there are three things being matched. Here we use the angle brackets to select which item(s) we want to take the value of --- we selected only one, so the result is that we take the value of the Term we parsed. If we selected more than one, the result would be a tuple of all the selected items. If we did not select any (i.e., "(" Term ")"), the result would be a tuple of all the items, and hence the result would be of type (&'input str, i32, &'input str).

GPT --- 在第二个替代定义 ("(" <Term> ")") 的情况下,匹配了三个项。在这里,我们使用尖括号来选择我们想要取值的项——我们只选择了一个,所以结果就是我们解析的 Term 的值。如果我们选择了多个项,结果将是一个包含所有选中项的元组。如果我们没有选择任何项(即 ("(" Term ")")),结果将是所有项的元组,因此结果的类型将是 (&'input str, i32, &'input str)

MST --- 在第二个选项“(” “)”的情况下,有三个东西被匹配。在这里,我们使用尖括号来选择要获取值---我们只选择一个项目的值,因此结果是我们获取我们解析的 Term 的值。如果我们选择了多个,结果将是所有选定项目的元组。如果我们没有选择任何(即“(” Term “)”),结果将是所有项目的元组,因此结果将是 (&'input str, i32, &'input str) 类型。

Speaking of types, you may have noticed that Term has no type annotation. Since we didn't write out own action code, we can omit the type annotation and let LALRPOP infer it for us. In this case, LALRPOP can see that Term must have the same type as Num, and hence that the type must be i32.

GPT --- 说到类型,你可能已经注意到 Term 没有类型注解。由于我们没有编写自己的动作代码,我们可以省略类型注解,让 LALRPOP 为我们推断类型。在这种情况下,LALRPOP 可以看出 Term 必须与 Num 具有相同的类型,因此类型必须是 i32

MST --- 说到类型,你可能已经注意到 Term 没有类型注释。由于我们没有写出自己的 action 代码,我们可以省略类型注释,让 LALRPOP 为我们推断它。在这种情况下,LALRPOP 可以看到 Term 必须与 Num 具有相同的类型,因此类型必须为 i32。

OK, let's look at the definition of Num we saw before from calculator1:

Num: i32 = <s:r"[0-9]+"> => i32::from_str(s).unwrap();

This definition too can be made somewhat shorter. In calculator2, you will find:

Num: i32 = r"[0-9]+" => i32::from_str(<>).unwrap();

Here, instead of giving the regular expression a name s, we modified the action code to use the funky expression <>. This is a shorthand that says "synthesize names for the matched values and insert a comma-separated list here". In this case, there is only one matched value, r"[0-9]+", and it produces a &'input str, so LALRPOP will insert a synthetic variable for that value. Note that we still have custom action code, so we still need a type annotation.

GPT --- 在这里,我们没有给正则表达式命名为 s,而是修改了动作代码,使用了特殊的表达式 <>。这是一个简写方式,表示“为匹配到的值生成名称,并在这里插入一个以逗号分隔的列表”。在这种情况下,只有一个匹配值 r"[0-9]+",它会生成一个 &'input str,因此 LALRPOP 会为该值插入一个合成变量。注意,我们仍然有自定义的动作代码,所以我们仍然需要类型注解。

MST --- 在这里,我们没有给正则表达式命名 s,而是修改了操作代码以使用 funky 表达式 <>。这是一个简写,表示 “synthesize names for the matched values and insert a comma-separated list here” 。在这种情况下,只有一个匹配的值 r“[0-9]+”,并且它会生成一个 &'input str,因此 LALRPOP 将为该值插入一个合成变量。请注意,我们仍然有自定义操作代码,因此我们仍然需要一个类型注释。

To control what values are selected when you use the <> expression in your action code, you can use angle brackets as we saw before. Here are some examples of alternatives and how they are expanded to give you the idea:

GPT --- 为了控制在动作代码中使用 <> 表达式时选择哪些值,你可以像之前看到的那样使用尖括号。以下是一些替代定义的示例,以及它们如何展开的,目的是帮助你理解:

MST --- 要控制在操作代码中使用 <> 表达式时选择的值,可以使用尖括号,如前所述。以下是一些替代方案的示例,以及如何扩展它们以为您提供想法:

Alternative Equivalent to
A => bar(<>) <a:A> => bar(a)
A B => bar(<>) <a:A> <b:B> => bar(a, b)
A B => (<>) <a:A> <b:B> => (a, b)
B => bar(<>) <a:A> B => bar(a)
<p:A> B => bar(<>) <p:A> B => bar(p)
=> bar(<>) <a:A> <b:B> => bar(a, b)
<p:A> <q:B> => bar(<>) <p:A> <q:B> => bar(p, q)
<p:A> B => Foo <p:A> B => Foo
<p:A> <q:B> => Foo <p:A> <q:B> => Foo

The <> expressions also works with struct constructors (like Foo {...} in examples above). This works out well if the names of your parsed values match the names of your struct fields.

GPT --- <> 表达式也可以与结构体构造函数一起使用(例如上面示例中的 Foo {...})。如果你解析的值的名称与结构体字段的名称匹配,这样的用法会非常方便。

MST --- <>表达式也适用于结构体构造函数(如上面示例中的 Foo {...})。如果解析的值的名称与 struct 字段的名称匹配,则效果很好。

标签:Term,5.3,inference,代码,---,LALRPOP,bar,Num,Type
From: https://www.cnblogs.com/Tifahfyf/p/18653172

相关文章

  • 箭头函数有prototype吗?为什么?
    箭头函数在JavaScript中没有自己的prototype属性。这是由箭头函数的设计决定的,主要基于以下几个原因:语法简洁性:箭头函数被设计为更简洁的函数表达式,主要用于简单的操作,而不是作为复杂对象或构造函数的定义。因此,去除prototype属性有助于保持箭头函数的简洁性。不绑定this:箭头函......
  • 在TypeScript中枚举和常量枚举有什么区别?
    在TypeScript中,枚举(Enums)和常量枚举(ConstEnums)都是用于定义一组命名的常量值的数据类型。然而,它们在编译时的行为和使用上存在一些关键差异。1.枚举(Enums)枚举是TypeScript提供的一种特殊的数据类型,它允许我们为一组数值定义友好的名字。默认情况下,枚举中的第一个成员被赋......
  • 在TypeScript中如何实现继承?
    在TypeScript中,可以通过extends关键字来实现类的继承。以下是一个简单的示例:classAnimal{name:string;constructor(name:string){this.name=name;}speak(){console.log(`${this.name}makesanoise.`);}}classDogext......
  • 在TypeScript中as语法是什么?
    在TypeScript中,as是一个类型断言操作符,它允许开发者明确地告诉TypeScript编译器某个值的类型。类型断言在TypeScript中是一种告诉编译器“我知道我在做什么,这个值就是这个类型”的方式。当你在TypeScript中遇到类型不明确的情况,或者TypeScript的类型推断与你的预期不符时,你可以......
  • 在TypeScript中说说你对声明合并的理解
    在TypeScript中,声明合并是一个重要的概念,它允许将多个具有相同名称的声明合并为一个声明。这一特性为前端开发提供了更大的灵活性和代码组织性。以下是我对TypeScript中声明合并的理解:声明合并的定义:声明合并是指TypeScript编译器在编译过程中,将程序中多处出现的同一名字的两......
  • 在TypeScript中tsconfig.json有什么作用?
    在TypeScript中,tsconfig.json文件是一个非常重要的配置文件,它用于指定TypeScript代码编译时的各种选项和目标。以下是tsconfig.json在前端开发中的主要作用:决定编译输出:通过tsconfig.json,可以设定TypeScript代码编译后输出的JavaScript版本,如ES3、ES5、ES6等。这确保了编译后的......
  • 你是如何编译TypeScript的文件?
    在前端开发中,编译TypeScript文件通常涉及几个步骤和工具。以下是一个基本的指南,介绍如何设置和编译TypeScript文件:1.安装Node.js和npm首先,确保你的开发环境中安装了Node.js和npm(Node.js的包管理器)。这些工具是前端开发的基础,并且npm用于安装TypeScript编译器和......
  • 在TypeScript中解释下rest参数的作用及规则
    在TypeScript(以及JavaScriptES6+)中,rest参数(...args)允许你将一个不定数量的参数作为一个数组传入函数。这在处理可变数量的参数时非常有用,尤其是当你不知道会有多少参数被传入函数时。作用:收集参数:rest参数可以收集函数被调用时传入的额外参数,并将它们放入一个数组中。灵......
  • 在TypeScript中如何创建变量?
    在TypeScript中创建变量的语法与JavaScript相似,但TypeScript为变量提供了类型注解的功能。类型注解可以帮助开发者更明确地了解变量的预期用途,并在编译阶段捕获类型错误。以下是在TypeScript中创建变量的一些示例:声明变量并指定类型:letage:number=25;letname:string=......
  • 在TypeScript中有哪些三斜杠指令?
    在TypeScript中,三斜杠指令(Triple-SlashDirectives)是一种特殊的注释语法,它以三个连续的斜线(///)开头。这些指令为TypeScript编译器提供额外的信息或指令,以帮助正确地编译和解析TypeScript代码。以下是在TypeScript中常见的三斜杠指令:///这个指令用于声明文件之间的依赖关系。......