Я пытаюсь определить свой собственный оператор в 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 к в не должен быть ноль. Как я могу зафиксировать?
Ну, в вашем коде есть одна проблема. Проще говоря, вы не добавили !! в таблицу операторов. Я дам вам небольшую справку по этому поводу.
Операторы в Io перемешиваются перед построением AST. Это означает, что мы должны вести список известных операторов с определенными уровнями старшинства, чтобы знать, какие из них связываются сильнее, чем другие. Мы делаем это в "OperatorTable". Если вы находитесь в REPL, вы можете посмотреть, как ее использовать, набрав в REPL "OperatorTable" (без кавычек). Это даст вам список операторов (генерируется динамически, поэтому новые операторы добавляются по мере их определения), а также примеры использования каждого типа операторов. Существует два типа:
Итак, в вашем примере код правильный, нам не нужно ничего менять. Однако нам не хватает одного бита кода, чтобы подсистема синтаксического анализа знала, как работать с вашим оператором. Я приведу пример, который предполагает, что вы хотите, чтобы он связывался так же жестко, как умножение.
OperatorTable addOperator("!!", 3)
Теперь мы можем увидеть, как это будет происходить, построив сообщение и посмотрев, как представлено его дерево. Снова в REPL, если мы напечатаем:
message(a !! b)
Мы увидим что-то вроде этого:
==> a !!(b)
Это так же, как и любой другой вызов метода, он должен где-то существовать, иначе вы получите ошибку. Вы можете использовать его так, как показано выше (с явными скобками), или использовать его так, как вы хотели в своем исходном вопросе, без явных скобок. Как и в случае с любым оператором, если вы не используете явные скобки, на вас распространяются правила старшинства, просто чтобы вы знали.
Надеюсь, это ответ на ваш вопрос.