Skip to content

Commit

Permalink
空の配列を初期値なしでreduceする時エラーを出すように (#600)
Browse files Browse the repository at this point in the history
* Update primitive-props.ts

* Update index.ts

* fix

* Update primitive-props.md

* Update CHANGELOG.md
  • Loading branch information
FineArchs authored May 10, 2024
1 parent 863a192 commit 5c7f11f
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# 未リリース分
- `Date:year`系の関数に0を渡すと現在時刻になる問題を修正
- シンタックスエラーなどの位置情報を修正
- `arr.reduce`が空配列に対して初期値なしで呼び出された時、正式にエラーを出すよう

# 0.18.0
- `Core:abort`でプログラムを緊急停止できるように
Expand Down
4 changes: 3 additions & 1 deletion docs/primitive-props.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,13 @@ _i_ 番目の文字が存在しない場合は null が返されます。
配列の要素のうち _func_ が true を返すようなもののみを抜き出して返します。
順序は維持されます。

### @(_v_: arr).reduce(_func_: @(_acm_: value, _item_: value, _index_: num) { value }, _initial_: value): value
### @(_v_: arr).reduce(_func_: Callback, _initial_: value): value
`Callback`: @(_acm_: value, _item_: value, _index_: num): value
配列の各要素に対し _func_ を順番に呼び出します。
各呼び出しでは、前回の結果が第1引数 _acm_ として渡されます。
_initial_ が指定された場合は初回呼び出しの引数が(_initial_, _v_\[0], 0)、
指定されなかった場合は(_v_\[0], _v_\[1], 1)となります。
配列が空配列であり、かつ _initial_ が指定されていない場合はエラーになります。従って基本的には _initial_ を指定しておくことが推奨されています。

### @(_v_: arr).find(_func_: @(_item_: value, _index_: num) { bool }): value
配列から _func_ が true を返すような要素を探し、その値を返します。
Expand Down
1 change: 1 addition & 0 deletions src/interpreter/primitive-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ const PRIMITIVE_PROPS: {
reduce: (target: VArr): VFn => FN_NATIVE(async ([fn, initialValue], opts) => {
assertFunction(fn);
const withInitialValue = initialValue != null;
if (!withInitialValue && (target.value.length === 0)) throw new AiScriptRuntimeError('Reduce of empty array without initial value');
let accumulator = withInitialValue ? initialValue : target.value[0]!;
for (let i = withInitialValue ? 0 : 1; i < target.value.length; i++) {
const item = target.value[i]!;
Expand Down
8 changes: 8 additions & 0 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import * as assert from 'assert';
import { expect, test } from '@jest/globals';
import { Parser, Interpreter, utils, errors, Ast } from '../src';
import { NUM, STR, NULL, ARR, OBJ, BOOL, TRUE, FALSE, ERROR ,FN_NATIVE } from '../src/interpreter/value';
let { AiScriptRuntimeError, AiScriptIndexOutOfRangeError } = errors;
Expand Down Expand Up @@ -2753,6 +2754,13 @@ describe('primitive props', () => {
eq(res, NUM(20));
});

test.concurrent('reduce of empty array without initial value', async () => {
await expect(exe(`
let arr = [1, 2, 3, 4]
<: [].reduce(@(){})
`)).rejects.toThrow('Reduce of empty array without initial value');
});

test.concurrent('find', async () => {
const res = await exe(`
let arr = ["abc", "def", "ghi"]
Expand Down

0 comments on commit 5c7f11f

Please sign in to comment.