Skip to content

feat: partition と partition_map を追加する - #87

Open
Javakky wants to merge 2 commits into
masterfrom
javakky/partition
Open

feat: partition と partition_map を追加する#87
Javakky wants to merge 2 commits into
masterfrom
javakky/partition

Conversation

@Javakky

@Javakky Javakky commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

概要(What / Why)

述語で 2 分割する partition と、分割と変換を同時に行う partition_map を追加します。

変更点

  • src/partition.phparray{0: true側, 1: false側}。両側とも元の順序を維持
  • src/partition_map.php — callback が array{0: bool, 1: 変換後の値} を返す。1 パスで振り分けと変換
  • tests/PartitionTest.php / tests/PartitionMapTest.php
  • composer.jsonautoload.files に 2 件追加

動作確認

  • 手動:
    • partition([1, 2, 3, 4], fn ($v) => $v % 2 === 0)[[2, 4], [1, 3]]
    • partition_map([20, 17], fn ($v) => $v >= 20 ? [true, $v] : [false, "minor($v)"])[[20], ['minor(17)']]
  • 自動:
    • vendor/bin/php-cs-fixer fix --dry-run --diff / vendor/bin/phpstan analyse -c phpstan.neon / vendor/bin/phpunit tests
    • 結果:OK (119 tests, 125 assertions) / PHPStan level 10 [OK] No errors / CS Fixer Fixed 0 of 33 files

補足(任意)

Either を作らずタプルで表現しています

Scala の partitionMapEither を返しますが、README の設計思想「新しいクラスを定義しない」に従い array{0: bool, 1: 値} にしました。partition と同じく 添字 0 が true 側で規約を揃えています。

@template を 1 本にした理由 (検証結果つき)

当初は @template L / @template R を切り、判別可能 union (array{0: true, 1: L}|array{0: false, 1: R}) から左右の型を分けようとしましたが、PHPStan 2.x はこの分離推論をしません\PHPStan\dumpType() で確認した結果:

  • callback の型自体は union のまま保たれる (Closure(int): (array{false, non-falsy-string}|array{true, int}))
  • それでも呼び出し結果は両側とも list<int|non-falsy-string>
  • callback を介さない最小形でも LR の両方に union 全体が推論される

潰れているのは関数本体ではなくテンプレート推論そのものなので、本体に /** @var L */ と言い切っても利用者側には分離が届きません。動かない型注釈は読み手に嘘をつくので、@template E 1 本に畳んで phpdoc に「左右で異なる型を返しても PHPStan 上は union として推論される」と明記しました。

同時に partition_map の実装を partition と同じ形 ($result = [[], []] + $side で振り分け) に揃えられたので、姉妹関数の非対称も解消しています。

この検証の経緯は tests/PartitionMapTest.php のヘルパーの docblock に残してあります (次に型パラメータを 2 本に分けたくなった人が同じ検証を繰り返さずに済むように)。

その他

  • 両側の件数の合計が入力件数と一致することを assoc 入力で テストしています (キー衝突が概念上ありうるのは assoc 側なので)
  • 振り分けは truthy 判定です。契約どおり bool を返す限り厳密比較との差はありません (phpdoc に明記)
  • @phpstan-param の条件型は付けていません (「assoc 入力 + MODE_LIST」が型エラーになるため。slice.php / map.php / intersect.php と同じ形)

Closes #59
Closes #23

🤖 Generated with Claude Code

Javakky added 2 commits July 27, 2026 16:14
配列を条件で 2 つに分割し、添字 0 に true 側、添字 1 に false 側を返す関数を追加した。両側とも元の並び順を保ち、Mode で キー保持 / 連番化を切り替える。

Closes #59
partition の分類と変換を 1 パスで同時に行う関数を追加した。コールバックが返す組の第 1 要素で振り分け、第 2 要素を変換後の値として使う。左右で値の型が変わってよい。

Closes #23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: partition を追加する feat: partition_map を実装

1 participant