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


我正试图在Io中定义自己的运算符,而且我很难过。我有一个对象:

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

但是当我打电话给它时,像这样:

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

但我得到一个例外,参数0到at必须不是nil。我该怎么办?


10329
2018-05-28 04:19


起源



答案:


好吧,你的代码中有一个问题。简单地说,你没有添加!!到操作员表。我会给你一些关于此的背景知识。

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

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

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

OperatorTable addOperator("!!", 3)

现在,我们可以看到如何通过构造消息并查看其树的表示方式来改变它。再次在REPL中,如果我们键入:

message(a !! b)

我们会看到这样的事情:

==> a !!(b)

这就像任何其他方法调用一样,它必须存在于某处,否则您将收到错误。您可以像上面显示的那样使用它(使用显式括号),或者您可以在原始问题中使用它,而无需使用明确的括号。与任何操作符一样,如果您不使用显式括号,则您必须遵守优先规则,这样您就知道了。

希望这能回答你的问题。


14
2018-05-28 04:26



谢谢你的回答,有助于了解。但是,我不明白为什么“n”在我的!!中为零!方法。
好吧,简单地说,在Io中,只有CFunctions(即在C代码中实现的方法,在特定索引处获取特定参数)要求您必须提供至少N个参数。当一个操作员不知道时,它不会被洗牌,这意味着你原来的x !! 2被视为:message(x !! 2)而不是message(x !!(2))。从!!在具有默认参数处理的Io代码中定义,发生的是未明确提供的任何参数都用“nil”填充。也就是说,参数得到定义,但它们指向零。这是您的问题的根源。 - jer
+1表示彻底的答案,也是关于代表优先顺序的OperatorTable的花絮。我没注意到。 - labyrinth
类似的问题。 Io专家看到它的几率非常低。也许你可以帮忙吗? stackoverflow.com/questions/27445142/... - Patrick McElhaney


答案:


好吧,你的代码中有一个问题。简单地说,你没有添加!!到操作员表。我会给你一些关于此的背景知识。

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

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

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

OperatorTable addOperator("!!", 3)

现在,我们可以看到如何通过构造消息并查看其树的表示方式来改变它。再次在REPL中,如果我们键入:

message(a !! b)

我们会看到这样的事情:

==> a !!(b)

这就像任何其他方法调用一样,它必须存在于某处,否则您将收到错误。您可以像上面显示的那样使用它(使用显式括号),或者您可以在原始问题中使用它,而无需使用明确的括号。与任何操作符一样,如果您不使用显式括号,则您必须遵守优先规则,这样您就知道了。

希望这能回答你的问题。


14
2018-05-28 04:26



谢谢你的回答,有助于了解。但是,我不明白为什么“n”在我的!!中为零!方法。
好吧,简单地说,在Io中,只有CFunctions(即在C代码中实现的方法,在特定索引处获取特定参数)要求您必须提供至少N个参数。当一个操作员不知道时,它不会被洗牌,这意味着你原来的x !! 2被视为:message(x !! 2)而不是message(x !!(2))。从!!在具有默认参数处理的Io代码中定义,发生的是未明确提供的任何参数都用“nil”填充。也就是说,参数得到定义,但它们指向零。这是您的问题的根源。 - jer
+1表示彻底的答案,也是关于代表优先顺序的OperatorTable的花絮。我没注意到。 - labyrinth
类似的问题。 Io专家看到它的几率非常低。也许你可以帮忙吗? stackoverflow.com/questions/27445142/... - Patrick McElhaney