feat: chunk_by に Mode を追加して assoc 対応にする - #90
Conversation
chunk_by の入力を list 限定から associative array まで広げ、 chunk 内部のキーの扱いを Mode で選べるようにした。 外側 (chunk の並び) は従来どおり常に list。 PR #75 では "associative array は順序保証が無いため非対応" と書いていたが、 PHP の配列は挿入順を保持するので assoc でも隣接関係は定義できる。 この理由は誤りだったので撤回する。 あわせて $callback に第 2 引数でキーを渡すようにし、 他の関数と揃えた。 PHP は宣言より多い引数を無視するため既存の呼び出しはそのまま動く。 戻り値の assoc 側は non-empty-array を付けていない。 non-empty-array<never, never> が chunk_by([], ...) の呼び出しで unresolvable になり、 利用者が空配列リテラルを渡せなくなるため。 list 側の non-empty-list は維持している。
|
Claude finished @Javakky's task in 4m 32s —— View job コードレビュー:
|
概要(What / Why)
chunk_byにModeを追加し、assoc 入力に対応させます。あわせて$callbackにキーを第 2 引数で渡します。chunk_byは #75 でマージしたときに「associative array は順序保証が無いため非対応」と書きましたが、この理由は誤りでした。PHP の配列は挿入順を保持するので、assoc でも「隣接する要素」は明確に定義できます。撤回します。
変更点
src/chunk_by.phpMode $mode = Mode::MODE_AUTOを追加。各 chunk の内部が mode に従う (外側は常に list)list<V>|array<K, V>に拡張$callbackをcallable(V, K): Rにしてキーを第 2 引数で渡す (他の関数と揃える)tests/ChunkByTest.php— 既存 7 ケースは無変更のまま 6 ケース追加動作確認
chunk_by(['a' => 1, 'b' => 1, 'c' => 2], fn ($v) => $v)→[['a' => 1, 'b' => 1], ['c' => 2]](AUTO で assoc)Mode::MODE_LIST→[[1, 1], [2]]vendor/bin/php-cs-fixer fix --dry-run --diff/vendor/bin/phpstan analyse -c phpstan.neon/vendor/bin/phpunit testsOK (110 tests, 120 assertions)/ PHPStan level 10[OK] No errors/ CS FixerFixed 0 of 31 files補足(任意)
互換性
$callbackに第 2 引数が増えますが、PHP は宣言より多い引数を無視するのでfn ($v) => $v形の既存呼び出しはそのまま動きます。$modeは既定値ありなので既存呼び出しは無変更で通り、既存の 7 ケースは 1 件も落ちていません。assoc 側の戻り値に
non-emptyを付けていない理由空の chunk は作らないので
list<non-empty-array<K, V>>と書きたいところですが、これを入れると空配列リテラルを直接渡す呼び出しが PHPStan level 10 で落ちます (実測)。
non-empty-array<never, never>が unresolvable になるためです (non-empty-list<never>は問題なし — list は値型しか持たないため)。list 側のnon-empty-list<V>は維持し、assoc 側だけarray<K, V>に緩めました。理由は phpdoc にも書いてあります。型注釈なしの
chunk_by([], ...)を直接書く回帰テストを入れてあります。Closes なし (対応 issue はありません。#75 の後追い改善です)
🤖 Generated with Claude Code