Object Invocation
シンボルに続いて()があるか無いかと、そのシンボルが指すものがMethodかどうかで、インタプリタの解釈が少し変わります。
Method | 非Method | |
x | x() | x |
x() | x() | x.invoke() |
Methodの場合は同じですが、非Methodの場合は、()があればinvokeが呼ばれ、無ければそれがそのまま返ります。
そして、Object.invokeはselfを返すので、大抵のオブジェクトにおいて、x()はxと変わりなく使え、invokeを定義してるオブジェクトにおいてのみ、関数のように振る舞うfunctorとなります。*1
Object.invokeに引数が与えられた場合、self.==が呼ばれます。これにより、invokeが未定義のオブジェクトは、そのままでpredicateとして機能します。
x: {invoke: 1} x //{invoke: 1} x() //1 x(1) //x.invoke(1) -> 1.== 1 -> true x(2) //x.invoke(2) -> 1.== 2 -> false y: `*[2] y //2 y() //2 y(1) //2 z: 3 z //3 z() //3 z(3) //true z(4) //false f: `pred[pred(1).? 't', 'nil'] f(1) //t f(2) //nil f(`*[true]) //t
リテラルに()を続けた場合は、数値だと型指定、文字列だとその文字列をシンボルとして扱うことになり、このObject Invocationの対象にはなりません。
そうしたい場合は、間に.を置くことで可能です。
"abc"() //abc()と同じ "abc".() //"abc".invoke()と同じ
関数の戻り値を呼ぶ場合も同じです。
`[ `x[ x.+ 1 ] ].().(2) //3