如何在 Io 编程语言中定义自己的运算符?

发布于 2024-09-04 00:37:39 字数 294 浏览 10 评论 0原文

我正在尝试在 Io 中定义我自己的运算符,但我遇到了困难。我有一个对象:

MyObject := Object clone do(
  lst := list()
  !! := method(n, lst at(n))
)

但是当我调用它时,像这样:

x := MyObject clone do(lst appendSeq(list(1, 2, 3)))
x !! 2

但我得到一个异常,即 at 的参数 0 不能为零。我该如何修复?

I'm trying to define my own operator in Io, and I'm having a hard time. I have an object:

MyObject := Object clone do(
  lst := list()
  !! := method(n, lst at(n))
)

But when I call it, like this:

x := MyObject clone do(lst appendSeq(list(1, 2, 3)))
x !! 2

But I get an exception that argument 0 to at must not be nil. How can I fix?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

美人迟暮 2024-09-11 00:37:39

嗯,您的代码中有一个问题。简单来说,你还没有添加!!到操作员表。我会给你一些背景知识。

Io 中的运算符在构造 AST 之前会被打乱。这意味着,我们必须维护一个具有特定优先级的已知运算符列表,以了解哪些运算符比其他运算符绑定更紧密。我们在“OperatorTable”中执行此操作。如果您在 REPL 中,则可以通过在 REPL 中键入“OperatorTable”(不带引号)来了解如何使用它。这将为您提供运算符列表(动态生成,因此新运算符在定义时添加),以及如何使用每种类型的运算符的示例。有两种类型:

  1. 二元运算符(例如 1 + 2,简称为“运算符”)
  2. 赋值运算符(例如 a := b)

因此,在您的示例中,您的代码是正确的;我们不需要改变任何东西。但是,我们缺少一点代码来使解析子系统知道如何处理您的运算符。我将提供一个示例,假设您希望它与乘法一样紧密地绑定。

OperatorTable addOperator("!!", 3)

现在,我们可以通过构造消息并查看其树的表示方式来了解如何对其进行打乱。再次在 REPL 中,如果我们键入:

message(a !! b)

我们将看到类似这样的内容:

==> a !!(b)

这就像任何其他方法调用一样,它必须存在于某处,否则您将收到错误。您可以像上面显示的那样使用它(带有显式括号),也可以在原始问题中按照您想要的方式使用它,而不需要显式括号。与任何运算符一样,如果您不使用显式括号,则必须遵守优先级规则,请您注意。

希望这能回答您的问题。

Well, there's one problem in your code. Simply put, you haven't added !! to the operator table. I'll give you a little background on this.

Operators in Io are shuffled before the AST is constructed. This means, that we have to maintain a list of known operators with certain precedence levels to know which ones bind tighter than others. We do this in the "OperatorTable". If you are in the REPL, you can see how to use it by typing "OperatorTable" into the REPL (without the quotes). This will give you a list of the operators, (generated dynamically, so new operators are added as they are defined), along with examples of how to use each type of operator. There are two types:

  1. Binary operators (1 + 2 for instance, called simply "operators")
  2. Assignment operators (a := b for instance)

So in your example, your code is right; we don't have to change anything there. However, we are missing one bit of code to make the parsing subsystem know how to handle your operator. I'll provide an example that assumes you want it to bind as tight as multiplication.

OperatorTable addOperator("!!", 3)

Now, we can see how this gets shuffled by constructing a message and looking at how its tree is represented. Again in the REPL, if we type:

message(a !! b)

We will see something like this:

==> a !!(b)

This is just like any other method call, it has to exist somewhere or else you will get an error. You can use it like it is shown above (with explicit parenthesis), or you can use it how you want to in your original question, without explicit parenthesis. As with any operator, you are subject to the rules of precedence if you do not use explicit parenthesis, just so you are aware.

Hope this answers your question.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文