【问题标题】:How do I define my own operators in the Io programming language?如何在 Io 编程语言中定义自己的运算符?
【发布时间】:2023-03-03 16:30:01
【问题描述】:

我正在尝试在 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 不能为 nil。我该如何解决?

【问题讨论】:

    标签: operators oop iolanguage


    【解决方案1】:

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

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

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

    所以在您的示例中,您的代码是正确的;我们不必在那里改变任何东西。然而,我们遗漏了一点代码来让解析子系统知道如何处理你的操作符。我将提供一个示例,假设您希望它像乘法一样紧密绑定。

    OperatorTable addOperator("!!", 3)
    

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

    message(a !! b)
    

    我们会看到这样的:

    ==> a !!(b)
    

    这就像任何其他方法调用一样,它必须存在于某个地方,否则你会得到一个错误。您可以像上面显示的那样使用它(带有明确的括号),或者您可以在原始问题中使用它,而无需明确的括号。与任何运算符一样,如果您不使用显式括号,则必须遵守优先规则,这只是您知道的。

    希望这能回答你的问题。

    【讨论】:

    • 感谢您的回答,对了解很有帮助。但是,我不明白为什么“n”在我的 !!方法。
    • 好吧,简单地说,在 Io 中,只有 CFunction(即在 C 代码中实现的在特定索引处获取特定参数的方法)要求您必须提供至少 N 个参数。当一个运算符不知道时,它不会被洗牌,这意味着你原来的 x !! 2 被视为:message(x !! 2) 而不是 message(x !!(2))。自从 !!在 Io 代码中使用默认参数处理定义,发生的情况是任何未显式提供的参数都用“nil”填充。也就是说,参数被定义,但它们指向 nil。这是您问题的根源。
    • +1 以获得彻底的答案,也用于表示优先顺序的 OperatorTable 的花絮。我没有注意到。
    • 类似的问题。被 Io 专家看到的几率非常低。也许你能帮忙? stackoverflow.com/questions/27445142/…
    猜你喜欢
    • 2017-12-22
    • 1970-01-01
    • 1970-01-01
    • 2015-02-11
    • 2019-09-14
    • 2011-07-16
    • 2015-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多