ログ日記

作業ログと日記とメモ

PHPStanとPsalmを混ぜた機能が欲しい

PHPStanはテンプレート+callableのネストに対応していた。

<?php

/**
 * @template A
 * @template B
 * @template X
 * @param callable(A,B):X $f
 * @return callable(A):(callable(B):X)
 */
function f2(callable $f)
{
    return function($a) use ($f){
        return function ($b) use ($f, $a){
            return $f($a, $b);
        };
    };
}

/**
 * @template A
 * @template B
 * @template C
 * @template X
 * @param callable(A,B,C):X $f
 * @return callable(A):(callable(B):(callable(C):X))
 */
function f3(callable $f)
{
    return function($a) use ($f){
        return function($b) use ($f, $a){
            return function($c) use ($f, $a, $b){
                return $f($a, $b, $c);
            };
        };
    };
}

function str_repeat_split(string $s, int $time, string $separator):string
{
    $arr = [];
    for ($i = 0; $i < $time; $i++){
        $arr[] = $s;
    }
    return implode($separator, $arr);
}
function test(): string
{
    $f = f3('str_repeat_split');
    $g = $f('abc');
    $h = $g(1);
    // $h(1);
    $h("\n");

    $i = f2('str_repeat');
    //$j = $i('abc')('def');
    $j = $i('abc')(2);

    $k = f2('str_repeat')('abc');
    //$l = $k('def');
    $l = $k(2);

    // $m = f2('str_repeat')('abc')('foo');
    $n = f2('str_repeat')('abc')(2);
    return nl2br($n);
}

コメントを外すと正しいエラーが報告される。

ここで、括弧がちょっとめんどいので

<?php

$n = f2('str_repeat')('abc')(2);
$n = f2('str_repeat', 'abc', 2);

引数と関数呼び出しの区別を無くして、並べて呼び出せるようにしたい。

機能だけなら
github.com
昔作ったんだけど、型チェックが効かない。


PsalmのConditional return typesの機能を使ってfunc_num_argsで戻り値の型を条件分岐させたい。
でもPsalmは

 * @return callable(A):(callable(B):(callable(C):X))

みたいな複雑な型に対応してないっぽい。



github.com
PHPStanにもconditional return typesの機能を付ける話は出ているみたい。

That's what this open feature request asks for, it's on my roadmap to implement this.

issue登録者が間違ってクローズしたものを作者が再オープンしていたので、しばらく待てば実装されるんだろうか。
もうすぐ1年経ってしまうけれども。