12

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 であってはならないという例外が発生します。どうすれば修正できますか?

4

1 に答える 1

14

さて、あなたのコードには1つの問題があります。簡単に言えば、あなたは追加していません!演算子テーブルに。これについて少し背景を説明します。

Ioのオペレーターは、ASTが構築される前にシャッフルされます。つまり、特定の優先度レベルを持つ既知の演算子のリストを維持して、どの演算子が他の演算子よりも緊密にバインドされているかを知る必要があります。これは「OperatorTable」で行います。REPLを使用している場合は、REPLに「OperatorTable」と入力して(引用符なしで)使用方法を確認できます。これにより、演算子のリスト(動的に生成されるため、定義されたとおりに新しい演算子が追加されます)と、各タイプの演算子の使用方法の例が表示されます。2つのタイプがあります:

  1. 二項演算子(たとえば、1 + 2、単に「演算子」と呼ばれます)
  2. 代入演算子(たとえばa:= b)

したがって、あなたの例では、あなたのコードは正しいです。そこでは何も変更する必要はありません。ただし、解析サブシステムにオペレーターの処理方法を認識させるためのコードが1ビット欠落しています。乗算と同じくらい緊密にバインドすることを想定した例を示します。

OperatorTable addOperator("!!", 3)

これで、メッセージを作成し、そのツリーがどのように表されるかを確認することで、これがどのようにシャッフルされるかを確認できます。再びREPLで、次のように入力すると、次のようになります。

message(a !! b)

次のようなものが表示されます。

==> a !!(b)

これは他のメソッド呼び出しと同じように、どこかに存在する必要があります。存在しないとエラーが発生します。上に示したように(明示的な括弧を付けて)使用することも、明示的な括弧を付けずに元の質問で好きなように使用することもできます。他の演算子と同様に、明示的な括弧を使用しない場合は、優先順位の規則に従う必要があります。

これがあなたの質問に答えることを願っています。

于 2010-05-28T04:26:18.033 に答える