オブジェクト#
Xarpiteでは、すべての値は親オブジェクトへの参照によって継承チェーンを作っています。
VALUEクラスオブジェクトのように親オブジェクトが無い値もあり、それは継承チェーンの根元に位置します。
オブジェクトリテラル{entry; ...}#
{ }はオブジェクトを作るリテラルです。
括弧内には、;で区切って0個以上のエントリーを書くことができます。
{ }は文レベルの場所に書かれても、コードブロックではなくオブジェクトリテラルとして振舞います。
$ xa '{a: 1; b: 2}'
# {a:1;b:2}
;で区切られた項がkey: valueの形式であることは強制ではなく、実際には2要素の配列、およびそのストリームを受け付けます。
エントリー演算子:は、オブジェクトリテラルとは本質的に無関係な、両辺を2要素の配列にする演算子です。
$ xa '{1 .. 3 | "Item$_": _ * 10; 4 .. 6 | ["Item$_", _ * 100]}'
# {Item1:10;Item2:20;Item3:30;Item4:400;Item5:500;Item6:600}
オブジェクトリテラル内での;の記述は柔軟です。
項の前後や中間に;を余計に多く書いても問題ありません。
また、改行は;の代わりになります。
$ xa '{
a: 1
b: 2
; ; ; c: 3; ; ;
}'
# {a:1;b:2;c:3}
オブジェクトリテラル内での変数宣言#
オブジェクトリテラル内で変数を宣言した場合、その変数はオブジェクトのエントリーに含まれつつ、オブジェクトリテラル内からも名前でアクセスできます。
$ xa '
{
fruit := "apple"
result: fruit & fruit
}
'
# {fruit:apple;result:appleapple}
変数にアクセスした時点で初期化される#
オブジェクトリテラル内で宣言された変数にアクセスすると、そのエントリはその時点でオブジェクトに代入されます。
$ xa '
{
result: fruit & fruit
fruit := "apple"
}
'
# {fruit:apple;result:appleapple}
この例では、resultの値を計算する時点ではfruitにはまだ値が設定されていないため、アクセスした時点で初期化が行われます。
stream.{}: オブジェクト化演算子#
オブジェクト化演算子は2要素の配列のストリームをオブジェクトに変換します。
$ xa '(["a", 1], ["b", 2]).{}'
# {a:1;b:2}
オブジェクト化演算子は、ストリームを返す変数や関数呼び出しと組み合わせてストリームを最短の記述でオブジェクトに変換する場合に便利です。
$ xa '({a: 1; b: 2; c: 3}() | (_.0 & "z": _.1 * 10)).{}'
# {az:10;bz:20;cz:30}
ストリームでない単一の2要素の配列でも動作します。
$ xa '["a", 100].{}'
# {a:100}
オブジェクトのストリーム化object()#
配列のストリーム化と似ていますが、こちらは各エントリーのキーと値で構成される配列のストリームを返します。
$ xa '{a: 1; b: 2; c: 3}()'
# [a;1]
# [b;2]
# [c;3]
以下は、オブジェクトを、各キーの末尾にzを付け、各値を10倍したオブジェクトにする例です。
$ xa '{a: 1; b: 2; c: 3}() | (_.0 & "z": _.1 * 10) >> TO_OBJECT'
# {az:10;bz:20;cz:30}
オブジェクト呼び出し#
オブジェクトに対してobject(key)のように関数呼び出しを行うと、その要素を取得します。
keyは文字列化されて評価されます。
keyがストリームだった場合、その各要素を文字列化して要素を取得するようなストリームを返します。
$ xa '{a: 1; b: 2; c: 3}("b")'
# 2
$ xa '{a: 1; b: 2; c: 3}("b", "a")'
# 2
# 1
$ xa '"b", "a", "c" >> {a: 1; b: 2; c: 3}'
# 2
# 1
# 3
オブジェクト呼び出しのオーバーライド#
オブジェクトの要素アクセスは実際には_(__)メソッドの呼び出しであり、オーバーライドができます。
これにより関数のように振舞うオブジェクトを作ることができます。
$ xa '
adder := {
`_(__)`: this, a, b -> a + b
}{}
adder(10; 20)
'
# 30
$ xa '
adder := {
`_(__)`: {
`_(__)`: this2, this1, a, b -> a + b
}{}
}{}
adder(10; 20)
'
# 30
オブジェクト呼び出しへの代入#
object(key) = valueのように代入呼び出しが可能です。
keyは文字列化されて評価されます。
$ xa '
obj := {fruit: "apple"}
obj("fruit") = "banana"
obj.fruit
'
# banana
オブジェクト呼び出しへの代入のオーバーライド#
オブジェクト呼び出しと同様に、代入操作も_(__)=_メソッドでオーバーライドできます。
オブジェクトのプロパティアクセス#
object.keyでオブジェクトの要素を取得できます。
keyが識別子だった場合、それは変数参照ではなく識別子自体を文字列として評価されます。
任意の式によるプロパティアクセスを行うには、object.(key)のようにkey部分を丸括弧で囲みます。
オブジェクトのプロパティアクセスへの代入#
object.key = valueでオブジェクトの要素に値を代入できます。
$ xa '
object := {
a: "one"
b: "two"
c: "three"
}
object.b = 99999
object
'
# {a:one;b:99999;c:three}
キーがそのオブジェクトにまだ存在しない場合は新たに追加されます。
オブジェクトのキーの削除#
object -= keyでオブジェクトからエントリーを削除できます。
$ xa '
object := {a: "apple"; b: "banana"; c: "cherry"}
object -= "b"
object
'
# {a:apple;c:cherry}
削除するキーが存在しない場合は何も起こりません。
$ xa '
object := {a: "apple"; b: "banana"; c: "cherry"}
object -= "d"
object
'
# {a:apple;b:banana;c:cherry}
右辺がストリームの場合、その各要素に対してキー削除を行います。
$ xa '
object := {a: "apple"; b: "banana"; c: "cherry"}
object -= "a", "c"
object
'
# {b:banana}
組み込み関数PARENT#
PARENT: 親オブジェクトの取得#
PARENT(value: VALUE): OBJECT | NULL
valueの親オブジェクト、もしくはNULLを返します。
親オブジェクトを指定して作られたオブジェクトに対しては、その親オブジェクトを返します。
継承チェーンの根元である値に対しては、NULLを返します。
それ以外の値に対しては、対応するクラス定数を返します。
valueがストリームの場合も、要素ごとではなく、ストリームそのものの親オブジェクトであるSTREAMを返します。
$ xa '
parent := {name: "Parent"}
child := parent{name: "Child"}
PARENT(child).name
'
# Parent
$ xa 'PARENT(VALUE)'
# NULL
$ xa 'PARENT({}) == OBJECT'
# TRUE
$ xa 'PARENT(1) == INT'
# TRUE
$ xa 'PARENT(INT) == VALUE'
# TRUE
$ xa 'PARENT(1, 2, 3) == STREAM'
# TRUE