CCさくらとは何の関係もありません。
clampは何かというと、CSSには既に実装されているのでそれを見るとわかりやすいですが、引数の数値を範囲内に納めてくれるというものです。
たとえばclamp(min=100, max=200)
に150を渡すと150が返ってくる、0を渡すと100が返ってくる、300を渡すと200が返ってくる、という感じです。
ということでPHPにもclampがほしいというRFCが提出されました。
以下は該当のRFC、PHP RFC: clampの紹介です。
PHP RFC: clamp
Introduction
clampは、値が範囲内にあるかをチェックします。
範囲内であればその値を返し、範囲外であれば境界値を返します。
ユーザランドの実装は幾つか存在しますが、minやmaxを使っているものも存在し、これらはコストがかかるため頻繁に呼ばれると遅くなります。
ユーザランド実装は呼び出しコストを考慮されていないものが多いので、言語での実装が望まれています。
Proposal
このRFCでは、新しい関数clampを提案します。
clamp ( int|float $num, int|float $min, int|float $max ) : int|float
3引数$num
、$min
、$max
を取ります。
$num
が$min
と$max
の間にあるかを調べ、範囲内であれば$num
を返します。
範囲外であれば、$min
と$max
のうち近い方を返します。
すなわち、$num > $max
であれば$max
を返し、$num < $min
であれば$min
を返します。
もし$max < $min
であれば、無効な値としてValueErrorを投げます。
何れかの値にNANが入ってきたときもValueErrorになります。
例としては以下のようになります。
clamp(num: 1, min: 0, max: 3); // 1 範囲内
clamp(num: 1, min: 2, max: 5); // 2 小さい
clamp(num: 4, min: 1, max: 3); // 3 大きい
clamp(num: 0, min: 2, max: 1); // clamp(): Argument #2 ($min) cannot be greater than Argument #3 ($max)
Backward Incompatible Changes
PHP自身の後方互換性のない変更はありません。
clamp()
は関数名として使用できなくなります。
Proposed PHP Version(s)
PHP8.x
Open Issues
NANの取り扱いについて。
#115085 / #115167
Implementation
References
感想
clampはIEEE754-2019で規格が決められているそうです。
見れないからわかりませんが、こんなものも定義されているんですね。
この関数は、PHPでも容易に実装できます。
function clamp(int|float $num, int|float $min, int|float $max):int|float {
if($max < $min){
throw new \ValueError('clamp(): Argument #2 ($min) cannot be greater than Argument #3 ($max)');
}
if($max < $num){
return $max;
}
if($min > $num){
return $min;
}
return $num;
}
プルリクでのCによる実装とほぼ同じです。
if (zend_compare(zmin, zmax) > 0) {
zend_argument_value_error(2, "must be smaller than or equal to argument #3 ($max)");
RETURN_THROWS();
}
if (zend_compare(zmax, zvalue) == -1) {
RETURN_COPY_VALUE(zmax);
} else if (zend_compare(zvalue, zmin) == -1) {
RETURN_COPY_VALUE(zmin);
} else {
RETURN_COPY_VALUE(zvalue);
}
従って、どうしても必要な関数というわけではなく、str_contains同様なくてもどうにかなるけどあれば便利なお助け関数という立ち位置ですね。
このRFC、2021年6月に提出され、その後一か月ほどでコードの実装は完成しました。
しかしその後ぱったりと消息が途絶え、進捗が停滞してしまいました。
作者は他のプロジェクトには様々にコミットしているので、飽きたか面倒臭くなったかでしょうか。
しかしその後も、これ欲しいよーというコメントがプルリクにちらほら追加されているので、もしかしたら今後レスキューされるかもしれません。
されないかもしれません。
ちなみに、以下がおそらくもっとも簡単な実装ですが、同時にRFCで言うところの遅い実装でしょう。
function clamp(int|float $num, int|float $min, int|float $max):int|float {
return max($min, min($max, $num));
}
ベンチ取ったわけじゃないからわかりませんが、見るからに遅そうですね。
しかし、この程度で有意差が出るほどclampを大量に呼び出すのっていったいどういうユースケースなんだろうか。