diff --git a/docs/primitive-props.md b/docs/primitive-props.md index 25b42f01..0045e873 100644 --- a/docs/primitive-props.md +++ b/docs/primitive-props.md @@ -128,6 +128,12 @@ _i_ 番目の文字が存在しない場合は null が返されます。 型: `num` 配列の要素数を取得します。 +### @(_v_: arr).at(_index_: num, _otherwise_?: value): value +配列の _index_ の位置の要素を返します。\ +_index_ が負の場合は末尾から数えます。\ +_index_ が範囲外の場合は、代わりに _otherwise_ を返します。\ +_otherwise_ が省略されている場合は`null`になります。 + ### @(_v_: arr).push(_i_: value): null **【この操作は配列を書き換えます】** 配列の最後に要素を追加します。 diff --git a/src/interpreter/primitive-props.ts b/src/interpreter/primitive-props.ts index 9c25f7cf..c89a4cb2 100644 --- a/src/interpreter/primitive-props.ts +++ b/src/interpreter/primitive-props.ts @@ -414,6 +414,11 @@ const PRIMITIVE_PROPS: { return removed[0] ?? NULL; }), + + at: (target: VArr): VFn => FN_NATIVE(async ([index, otherwise], opts) => { + assertNumber(index); + return target.value.at(index.value) ?? otherwise ?? NULL; + }), }, error: { diff --git a/test/index.ts b/test/index.ts index ff03baff..d6508855 100644 --- a/test/index.ts +++ b/test/index.ts @@ -3183,6 +3183,46 @@ describe('primitive props', () => { ARR([NUM(1), NUM(4), NUM(5), NUM(6), NUM(7)]) ])); }); + + test.concurrent('at (without default value)', async () => { + const res = await exe(` + let arr1 = [10, 20, 30] + <: [ + arr1 + arr1.at(0), arr1.at(1), arr1.at(2) + arr1.at(-3), arr1.at(-2), arr1.at(-1) + arr1.at(3), arr1.at(4), arr1.at(5) + arr1.at(-6), arr1.at(-5), arr1.at(-4) + ] + `); + eq(res, ARR([ + ARR([NUM(10), NUM(20), NUM(30)]), + NUM(10), NUM(20), NUM(30), + NUM(10), NUM(20), NUM(30), + NULL, NULL, NULL, + NULL, NULL, NULL, + ])); + }); + + test.concurrent('at (with default value)', async () => { + const res = await exe(` + let arr1 = [10, 20, 30] + <: [ + arr1 + arr1.at(0, 100), arr1.at(1, 100), arr1.at(2, 100) + arr1.at(-3, 100), arr1.at(-2, 100), arr1.at(-1, 100) + arr1.at(3, 100), arr1.at(4, 100), arr1.at(5, 100) + arr1.at(-6, 100), arr1.at(-5, 100), arr1.at(-4, 100) + ] + `); + eq(res, ARR([ + ARR([NUM(10), NUM(20), NUM(30)]), + NUM(10), NUM(20), NUM(30), + NUM(10), NUM(20), NUM(30), + NUM(100), NUM(100), NUM(100), + NUM(100), NUM(100), NUM(100), + ])); + }); }); }); diff --git a/unreleased/arr-at.md b/unreleased/arr-at.md new file mode 100644 index 00000000..ce3a746f --- /dev/null +++ b/unreleased/arr-at.md @@ -0,0 +1 @@ +- `arr.at`を追加