cba什么意思| 喉咙干痒是什么原因| 伤食是什么意思| 牙齿出血是什么病| 蜈蚣为什么不能打死| 主人是什么意思| 14时是什么时辰| 03属什么| 奶酪是什么东西| 男人吃什么更持久| 什么样的人容易中风| 井代表什么数字| 纳豆激酶有什么作用| 八项规定的内容是什么| 交警中队长是什么级别| 北京大学什么专业最好| 长痔疮有什么症状| 吃什么能提高代谢| 太阳为什么能一直燃烧| 吃什么对肺结节好| 儿童手指头脱皮什么原因引起的| 女人脸肿是什么原因引起的| 感冒了吃什么水果比较好| 沂字五行属什么| 尼莫地平片治什么病| 梦见玻璃碎了什么意思| 长湿疹是什么原因引起的| 我是小姨的什么人| hdl是什么意思| 睾丸瘙痒是什么原因| 热辐射是什么| 横纹肌溶解症是什么原因造成的| 照字五行属什么| 水果的英文是什么| 牛的四个胃分别叫什么| 漱口杯什么材质好| 治疗神经痛用什么药最有效| 小姑娘为什么会得多囊卵巢| 例行检查是什么意思| 结节是什么症状| 怀孕生化了是什么原因| 不什么声什么| 洗衣机单漂洗是什么意思| 空是什么生肖| hcg低有什么补救的办法| 为什么吃了饭就想睡觉| 蝶变是什么意思| 手痒脚痒是什么原因| 金鱼可以和什么鱼混养| 金不换是什么菜| 御是什么意思| 胆结石能吃什么水果| 什么人容易得脑溢血| 麦芽糊精是什么| 巧囊是什么| 什么动物可以贴在墙上| 癣是什么原因引起的| 紫花地丁有什么功效| zn是什么元素| 膝关节退行性变是什么意思| 老年人吃什么增强免疫力| 耳鸣吃什么药| 何首乌泡酒有什么作用| adr是什么| 吃什么吐什么| 做了胃镜多久可以吃东西吃些什么| 猪肚和什么煲汤最好| 惹上官司是犯了什么煞| 6月14号是什么星座| 室内传导阻滞什么意思| 蛋糕裙适合什么人穿| ebv病毒是什么| 子宫彩超能检查出什么| 超霸是什么意思| 十滴水是什么| 蛋白粉和胶原蛋白粉有什么区别| 诺欣妥是什么药| 人工念什么字| 站久了腰疼是什么原因| 交期是什么意思| 什么是初心| 小姑独处是什么意思| 四季春是什么茶| 调经止带是什么意思| 美味佳肴是什么意思| 什么是超纤皮| 父亲节送爸爸什么礼物| 愤青什么意思| 叔叔的儿子叫什么| 甲状旁腺激素高吃什么药| 恶心想吐胃不舒服是什么原因| 列巴是什么| 经常拉肚子什么原因| 氢什么意思| 心心相惜是什么意思| gc是什么| 脑炎是什么病严重吗| 梦见自己又结婚了是什么意思| 芒果吃多了有什么坏处| 为什么手指会发麻| 龙井是什么茶| 意识是什么| 包皮是什么样子图片| 甘露醇是什么| 西芹和芹菜有什么区别| 小蛮腰是什么意思| 泡蛇酒用什么药材最好| 妾是什么意思| 透疹是什么意思| 什么姿势睡觉最好| 无垠是什么意思| 为什么屎是黑色的| 白茶为什么叫白茶| 九二年属猴的是什么命| hl是胎儿的什么| 鹅蛋炒香菜治什么病| 扁桃是什么水果| 什么是红眼病| 皮肤过敏挂什么科| 豆奶不能和什么一起吃| 中性粒细胞低是什么原因| 双肾盂分离是什么意思| 白带清洁度lll度是什么意思| 美国为什么有两块土地| 脚底板疼痛是什么原因| 飞蚊症是什么原因引起的| 人参适合什么人吃| 龙井是什么茶| 什么人容易高反| 猫猴子是什么| 稽留流产是什么原因| 磷高有什么症状和危害| 卖什么小吃简单挣钱| 广西有什么市| 圆脸适合什么短发| 吃什么东西补血最快| 胆囊壁毛糙吃什么药| 便秘喝什么药| 梦见豹子是什么预兆| 月经稀发是什么意思| 精囊在什么位置| 展开的近义词是什么| 口腔溃疡为什么那么痛| ac是什么元素| 脑脊液是什么| 试纸什么时候用最准确| 胃切除手术后吃什么好| 义举是什么意思| 梦见自己出轨是什么意思| 火气重喝什么茶| 什么是总胆固醇| 吃茶叶蛋有什么好处和坏处| 上呼吸道感染吃什么消炎药| 鞠婧祎什么学历| 细菌感染是什么引起的| 什么是接触性皮炎| 女人为什么会得霉菌| 什么是格言| 检查免疫力都需要化验什么项目| 胃寒吃什么食物暖胃| 血压低什么原因| 无条件是什么意思| 单反是什么意思| 点了斑不能吃什么| 鼻炎吃什么药见效快| 汁字五行属什么| 抱怨是什么意思| 未羊是什么意思| 单核细胞高是什么原因| 古代医生叫什么| 离岸人民币什么意思| 中午1点是什么时辰| 左脚麻是什么原因| 脚癣用什么药| 什么水不能喝脑筋急转弯| 耳洞发炎流脓用什么药| 把碗打碎了有什么征兆| 过敏性鼻炎吃什么药能快速缓解| 套马的汉子你威武雄壮是什么歌| 12月28是什么星座| 四个火念什么| 曙光是什么意思| 炸酥肉用什么肉最好吃| 4月23是什么星座| 脚心发热是什么原因| 相亲为什么不能拖太久| 酸菜鱼一般加什么配菜| 跟腱炎贴什么膏药最好| 男孩学什么专业有前途| 维生素b族适合什么人吃| 日光性皮炎用什么药膏| 硝化细菌是什么| g代表什么单位| 一什么小狗| 什么样的葡萄| 多囊卵巢是什么原因造成的| 做活检意味着什么| 喝酒后呕吐是什么原因| 糖尿病可以吃什么菜| 上海的市花是什么| 什么叫生酮饮食| 虹霓是什么意思| 首战告捷什么意思| 蝉联是什么意思| 碧是什么颜色| 女士内裤用什么洗最好| 被蟑螂咬了擦什么药| 尿白细胞3十什么意思| 牛肉烧什么菜最好吃| 肚子大挂什么科| 嘴下面起痘是什么原因| 八格牙路是什么意思| 多吃苹果有什么好处| 牙齿发软是什么原因| 脾虚喝什么泡水比较好| 冰心原名叫什么| 润滑油是干什么用的| 印堂跳动是什么预兆| 小名是什么意思| 流产挂什么科| 颈部淋巴结挂什么科| 鼻甲肥大吃什么药最好| 岑岑是什么意思| 什么属于轻微糖尿病| nak是什么牌子| 透骨草治什么病最有效| 药流是吃什么药| 阑尾粪石是什么| 白头发缺什么维生素| 粘米粉可以做什么好吃的| 凉虾是什么| exo什么时候出道的| pms是什么| 梦见腿断了是什么意思| 视黄醇结合蛋白是什么| 老年痴呆挂什么科| 割伤用什么药愈合伤口| pmid是什么意思| 吸水石是什么石头| 飞蛾飞进家里预示什么| 肚子左边是什么部位| 参事是什么级别| 开庭前家属做什么准备| 破冰是什么意思| 以身相许是什么意思| 周边什么意思| 脾胃气滞吃什么中成药| 办结婚证需要什么| 豆绿色是什么颜色| 12月17日什么星座| 火六局是什么意思| 梦见搬家是什么意思| 生物冰袋里面是什么| 奶霜是什么| 最贵的烟是什么牌子| 心肌酶是查什么的| 控制欲是什么意思| 有代沟是什么意思| 为什么会气虚| 吃什么不会便秘| 产褥热是什么病| 石斛有什么功效和作用| 5月13日什么星座| 什么是局限性肺纤维化| 百度
rfc:operator_overrides_lite

“人民有信心”激发更加强大的奋进力量

Introduction

百度   作者:邓海建  继去年12月北京市出台中国首个自动驾驶路测规定之后,上海、重庆、深圳等地相继发布相关政策,对自动驾驶汽车上路测试进行规范,保障公众交通安全。

Nearly three years ago, PHP RFC: User Defined Operator Overloads was declined due to scope and new syntax concerns. However, the GMP class, which represents integer numbers in the GMP extension, was (accidentally) left non-final. This RFC explores the potential of extending GMP with a limited form of operator overriding, providing cleaner expressions for mathematical constructs and allowing new types of numerical representations such as units, complex numbers, and more.

This is to integers as ArrayAccess is to arrays, and Stringable is to strings, providing a simplified framework for defining integer mathematics, such as units.

What this is not

This is not a full operator overrides implementation; it is much simpler and it does not stop us from implementing that in the future. It, does, however seek to be a polar opposite of the PHP RFC: User Defined Operator Overloads RFC.

Why the GMP extension?

Several curious people have wondered why this is focused on the GMP extension. The reasons are quite simple:

  1. Numbers are surprisingly hard to implement “from scratch” (which is required if implemented in another extension) and libraries like GMP/BCMath are great libraries that make this simple.
  2. GMP has a practically infinite numerical range, meaning if you wanted to write a “Duration” library that counted in nanoseconds, you could have a range larger than 292 years (the limit for 64 bit machines using PHP_INT_MAX).
  3. People using the GMP extension are already familiar with the way overloading works in the engine.
  4. The extension already has all the plumbing in-place to handle casting, operator overloads, and all in an OOP oriented way.

Proposal

The \GMP class will be changed to the following signature:

readonly class GMP
{
    public function __construct(int|string|GMP $num = 0, int $base = 0) {}
 
    public function __serialize(): array {}
 
    public function __unserialize(array $data): void {}
 
    protected function add(GMP|int|string $left, GMP|int|string $right): GMP {}
 
    protected function multiply(GMP|int|string $left, GMP|int|string $right): GMP {}
 
    protected function subtract(GMP|int|string $left, GMP|int|string $right): GMP {}
 
    protected function divide(GMP|int|string $left, GMP|int|string $right): GMP {}
 
    protected function mod(GMP|int|string $left, GMP|int|string $right): GMP {}
 
    protected function pow(GMP|int|string $base, GMP|int|string $exp): GMP {}
 
    protected function comparable(GMP|int|string $op1, GMP|int|string $op2): bool {}
}

The changes are listed below:

  1. The class is made readonly to prevent developers from using state in inherited types.
  2. The constructor accepts another GMP instance instead of only string|int
  3. Mathematical methods are added to the class as protected. It is expected that developers wanting to support an operation make the associated operation public.

For any existing GMP code, absolutely nothing changes. The extension's behavior ONLY changes when the developer extends the GMP class and uses it mathematically. To be usable, the developer must override the desired operations and make them public. This ensures the class can be used even if the GMP extension is unavailable. A polyfill is included in the example below, which can be included in libraries that use this functionality.

Note the lack of equals, less-than, and greater-than operators. These are deliberately left out and replaced by a “comparable” method where the developer can indicate whether the two objects are compatible. They are left out for several reasons:

  1. PHP reorders comparables as needed
  2. The core tenant here is that these objects should represent types of integers, and it is expected that they are internally comparable but possibly not comparable to other types. For example, the number of goats on a farm may not be comparable to the speed of a car.

Shift and bitwise operations are also left out of the class because it is expected that these behaviors won't change for any type of number that could be implemented here.

Below is a listing showing a polyfill, a Duration class that only allows adding, multiplying, and exponentiation with scalars and is only comparable to Durations. Further, it cannot be negative.

<?php
 
if(!class_exists('GMP')) {
    // polyfill for completion
    readonly class GMP {
        public function __construct(private int|string|GMP $num) {}
 
        protected function add(GMP|int|string $left, GMP|int|string $right): GMP {
            return new self($left?->num + $right?->num);
        }
 
        protected function multiply(GMP|int|string $left, GMP|int|string $right): GMP {
            return new self($left?->num * $right?->num);
        }
 
        protected function subtract(GMP|int|string $left, GMP|int|string $right): GMP {
            return new self($left?->num - $right?->num);
        }
 
        protected function divide(GMP|int|string $left, GMP|int|string $right): GMP {
            return new self($left?->num / $right?->num);
        }
 
        protected function mod(GMP|int|string $left, GMP|int|string $right): GMP {
            return new self($left?->num % $right?->num);
        }
 
        protected function pow(GMP|int|string $base, GMP|int|string $exp): GMP {
            return new self($base?->num ** $exp?->num);
        }
 
        protected function comparable(GMP|int|string $op1, GMP|int|string $op2): bool {
            return is_numeric($op1) && is_numeric($op2);
        }
    }
}
 
readonly class Duration extends GMP {
    public function __construct(int|string|GMP $num = 0)
    {
        if($num < 0) {
            throw new ArithmeticError('Duration cannot be negative.');
        }
 
        parent::__construct($num);
    }
 
    private function assertValidScalar(mixed $maybeScalar, string $operation): void {
        if(is_numeric($maybeScalar)) {
            return;
        }
 
        if(get_class($maybeScalar) === 'GMP') {
            return;
        }
 
        throw new ValueError("Can only perform $operation on GMP or int. Got " . get_debug_type($maybeScalar) . " instead.");
    }
 
    private function guardScalars(GMP|int|string $left, GMP|int|string $right, string $operation): void
    {
        if($left === $this) {
            $this->assertValidScalar($right, $operation);
            return;
        }
 
        if($right === $this) {
            $this->assertValidScalar($left, $operation);
            return;
        }
 
        throw new LogicException('$left or $right must be the same instance as $this.');
    }
 
    private function getResult(GMP $result): self {
        return new self($result);
    }
 
    public function add(GMP|int|string $left, GMP|int|string $right): static
    {
        $this->guardScalars($left, $right, 'addition');
 
        return $this->getResult(parent::add($left, $right));
    }
 
    public function multiply(GMP|int|string $left, GMP|int|string $right): GMP
    {
        $this->guardScalars($left, $right, 'multiplication');
 
        return $this->getResult(parent::multiply($left, $right));
    }
 
    public function pow(GMP|int|string $base, GMP|int|string $exp): GMP
    {
        $this->assertValidScalar($exp, 'exponentiation');
 
        if($base !== $this) {
            throw new LogicException('$base must be the same instance as $this.');
        }
 
        return $this->getResult(parent::pow($base, $exp));
    }
 
    public function comparable(GMP|int|string $op1, GMP|int|string $op2): bool
    {
        return $op1 instanceof self && $op2 instanceof self;
    }
}
 
$duration = new Duration(10);
$other = new Duration(200);
$regular = new GMP(10);
 
function do_op($description, $op): void {
    global $duration, $other, $regular;
    try {
        $result = eval('return ' . $op . ';');
        echo "$description: $op = $result" . PHP_EOL;
    } catch (Throwable $exception) {
        echo "$description: $op = [" . get_class($exception) . ': ' . $exception->getMessage() . ']' . PHP_EOL;
    }
}
 
do_op('Duration', '$duration');
do_op('Regular', '$regular');
do_op('Other', '$other');
 
do_op('Regular', '$regular + 10');
do_op('Duration', '$duration + 10');
do_op('Duration + Duration', '$duration + $other');
do_op('Duration + Regular', '$duration + $regular');
do_op('Division not allowed', '$duration / 10');
do_op('Multiplication', '$regular * 10');
do_op('No negatives', '$duration + -20');
do_op('Comparison', '$duration < $other');
do_op('Comparison failure', '$duration < 20');
 
/**
 * Output:
 * Duration: $duration = 10
 * Regular: $regular = 10
 * Other: $other = 200
 * Regular: $regular + 10 = 20
 * Duration: $duration + 10 = 20
 * Duration + Duration: $duration + $other = [ValueError: Can only perform addition on GMP or int. Got Duration instead.]
 * Duration + Regular: $duration + $regular = 20
 * Division not allowed: $duration / 10 = [Error: Invalid callback Duration::divide, cannot access protected method Duration::divide()]
 * Multiplication: $regular * 10 = 100
 * No negatives: $duration + -20 = [ArithmeticError: Duration cannot be negative.]
 * Comparison: $duration < $other = 1
 * Comparison failure: $duration < 20 = [ArithmeticError: Can't compare incompatible types]
 */

The following exceptions can be thrown by the engine while attempting to perform mathematical operations:

  • Error: when trying to perform an unsupported operation, which shows as “Invalid callback Duration::divide, cannot access protected method Duration::divide()”
  • ArithmeticError: when ANY participating comparison indicates that it is not comparable: “Can't compare incompatible types: Duration to int”

Additionally, the implementor may throw additional exceptions, such as a ValueError in the example above, to indicate that something is not possible to the developer.

Backward Incompatible Changes

There are no backward incompatible changes. Existing GMP-based code will remain unaffected.

Proposed PHP Version(s)

8.4 if time allows, or the next version.

RFC Impact

To SAPIs

No impact.

To Existing Extensions

Only GMP will be affected.

To Opcache

There should be no impact to Opcache.

Open Issues

None, yet.

Unaffected PHP Functionality

Code using the GMP extension without extending it will remain unchanged.

Future Scope

  • support for other operators
  • serialization/unserialization
  • support for non-integers via BCMath

Proposed Voting Choices

  • 2/3 YES|NO vote: Allow extending the \GMP class and use a form of operator overloading
  • 2/3 YES|NO secondary vote: Disallow extending the \GMP class if this RFC fails

Patches and Tests

Prototype patch: PR 14730

Implementation

After the project is implemented, this section should contain

  1. a link to the git commit(s)
  2. a link to the PHP manual entry for the feature
  3. a link to the language specification section (if any)

References

Links to external references, discussions or RFCs

Rejected Features and Concerns

A separate extension

On paper, a separate extension sounds like a good idea. However, I've attempted this with varying degrees of success. Reimplementing mathematics is not straightforward or a good idea when libraries like GMP do a much better job. Since there is already a GMP extension, it makes sense to merge it with that extension instead of forking it. If this RFC is rejected, it is rather straightforward to fork the extension and create a new one. However, that will certainly cause problems in environments where the standard GMP extension is installed instead.

Full Operator Overloading

Some people on the list have voiced their opinion that we should revisit full operator overloading. This RFC does not prevent us from revisiting that in the future, but it is outside the scope of this RFC.

More Operators

There are many more operators that could be implemented. However, another concern was raised that people may “abuse” this feature to implement arbitrary objects that do strange things with operators. Thus, the scope is kept to “obviously integer-y things,” and the GMP extension goes to great lengths to have the engine treat its objects as numbers.

rfc/operator_overrides_lite.txt · Last modified: by 127.0.0.1

?
静对什么 人为什么会抑郁 枯草热是什么病 你算什么东西 心衰吃什么药好
角是什么结构 面肌痉挛挂什么科 绝对值是什么意思 闭日是什么意思 头疼头胀是什么原因
夏令时什么时候开始和结束 胃镜取活检意味着什么 3.7号是什么星座 胃肠炎可以吃什么水果 微波炉加热用什么容器
胃胀气用什么药最好 一月十二号是什么星座 胃疼什么症状 现象是什么意思 怹是什么意思
什么叫肠化生hcv8jop5ns9r.cn 什么是富氢水hcv8jop2ns4r.cn 为什么醋能让疣体脱落hcv9jop6ns8r.cn 胸片能查出什么hcv9jop3ns5r.cn 封神榜讲的是什么故事wuhaiwuya.com
生吃紫苏叶有什么功效gysmod.com 二型血糖高吃什么药好hcv7jop6ns0r.cn 小病不治下一句是什么hcv7jop6ns0r.cn 唐氏宝宝是什么意思hcv8jop9ns9r.cn 蜂蜜水什么时候喝比较好hcv7jop5ns6r.cn
为什么会莫名其妙流鼻血hcv8jop3ns5r.cn 喝竹叶水有什么好处hcv8jop3ns6r.cn 白蜡金命五行缺什么hcv8jop9ns0r.cn 奥地利讲什么语言hcv9jop1ns5r.cn 副局长什么级别gangsutong.com
什么东西最养胃cj623037.com 买房要看什么hcv7jop7ns2r.cn 天孤星是什么意思hcv8jop9ns9r.cn 房产证和土地证有什么区别hcv9jop4ns5r.cn 智齿冠周炎吃什么消炎药hcv8jop0ns5r.cn
百度