2306d的闭包问题

news/2024/11/17 6:48:16/

原文
首先,D的闭包是个好主意.我使用了C++的成员函数指针;它们在语法上很糟糕,但概念很好,而闭包更好.
D的闭包有些问题,有些是明显错误,有些是不应该不在语言中的改进.

不能调用某些闭包

这很奇怪,但这是真的.
一个问题是不变目前没有扩展到闭包环境.要求常和不变的传递性时,这是个错误:

const(void delegate()) dg = &obj.method;

(因为按变量声明,)不应该可调用dg:dg获得的引用不应更改它的环境,但不能保证dg不会这样:方法不一定会用注解.

const(void delegate() const) dg = &obj.constMethod;

DG有个承诺不改变环境的常注解;因此,可调用它.如果不是用(或不变)注解常方法(constMethod),则赋值将不管用.

拒绝了一些有效且有用的转换

因为闭包是紧密绑定的环境-函数对,因此有不变注解的闭包应按可变闭包隐式转换:(因为被调函数根本不会这样做,调用闭包,或其他方式)重新注解,不改变不会更改环境,且重新赋值注解可变闭包也不改变这一点,因为不能单独赋值环境和函数指针.

另一个应正常工作的是函数指针闭包转换,事实上,因为函数指针没有环境,所以它的环境不变的:

void f() @safe { writeln("Hello"); }
void delegate() @safe immutable dg = &f; //今天:是错误,解决方法:
//
void delegate() @safe immutable dg = () @trusted {void delegate() @safe immutable result = null;result.funcptr = cast(typeof(result.funcptr)) &f;return result;
}();
dg(); //(如期)打印"你好"

有以下序列:

void function() -> 
void delegate() immutable -> 
void delegate() const -> 
void delegate()

第一个是值转换,其他是引用转换.
直接使用λ时,第一个转换有效,但当把λ赋值给自动变量,然后按参数传递给闭包类型参数时,则不会转换.

推导环境限定符

适合闭包.(对对象-方法对地址,该方法告诉了精确的限定符).闭包有闭包或函数指针类型,可以说,它应该有有最多保证的类型(如,因此它推导属性).

但有时,闭包不会推导类型限定符.

int x;
auto dg = () => x;
pragma(msg, typeof(dg)); //int delegate() pure nothrow @nogc @safe

类型没有错,只是缺少了:它缺少,因为闭包抓了x,且在运行时闭包不会改变x.则为什么不应是它的属性之一?不过,可显式地请求:

int x;
auto dg = () const => x;
pragma(msg, typeof(dg)); //int delegate() const pure nothrow @nogc @safe

它是否兑现承诺?不:

int x;
auto dg = () const => x += 1; //为什么可以这样

注意,dg是纯的.0参数常纯闭包不能影响值:

int x = 0;
assert(x == 0); //通过,为什么可以这样,int delegate() const pure nothrow @nogc @safe
auto dg = () const => x += 1; //
pragma(msg, typeof(dg)); //
dg();
assert(x == 1); //通过,但可能会因为优化而失败

不变呢?

immutable int x;
auto dg = () => x;
pragma(msg, typeof(dg)); //不变(int) delegate() pure nothrow @nogc @safe

不变(整)返回突出类型,但这不是重点.有趣的是,dg抓的所有事物(即x)都是不变的.可显式要求不变:

immutable int x;
auto dg = () immutable => x;pragma(msg, typeof(dg)); //不变(整) 闭包() 不变 纯 不抛 @nogc @safe

只有在可隐式遗忘这些保证,函数而不是闭包的推导和不变的推导时才有意义.

无法表示某些类型

类型构造器属性,可表示闭包的底层函数不得改变其环境,或环境是完全不变的.
而应用构造类型器至整个闭包类型后,它可能会(相反:有时候应该)不可用,这很糟糕.
如果想表达不应重新赋值闭包怎么办?表明:函数指针是常或不变的(不重要),但环境可任意.我知道它不常用,但有时有用.

如果按(dg.ptr,dg.funcptr)对对待dg闭包,好像dg.funcptr,而不管dg.ptr(环境).
不可赋值组件使不可赋值.完成.很容易.只有语言没有概念,也没有语法.如果可以,语法可以是int delegate 常(),同样与常(常(int)[])常(int[])类型相同一样,常(整 闭包 常())常(整 闭包())相同.

我认为不管用的原因函数和闭包有不同调用约定.为了允许把函数指针转换为闭包,编译器必须生成一个蹦床.
关于环境限定符,还存在以下问题,这里:

"std.functional.toDelegate"可生成蹦床,这里.
但是,它会生成非限定环境:

import std.functional;
void foo()@safe{}
void main(){void delegate()immutable dg=toDelegate(&foo); //错误
}

它必须这样,因为DMD错误地拒绝不变环境到非限定环境的转换.


http://www.ppmy.cn/news/451208.html

相关文章

Qt 每月收支计算

Qt 每月收支计算,针对每月有支出(房贷、车贷、花呗、借呗)的情况,计算收支明细,直观看到未来的个人经济情况,培养良好的消费习惯,进行理性的财富支配,量入为出。 #include "mai…

哈希表--day3--(leetcode349/leetcode350)

leetcode349. 两个数组的交集 链接 基本思路 注意题目特意说明:输出结果中的每个元素一定是唯一的,也就是说输出的结果的去重的, 同时可以不考虑输出结果的顺序 这道题用暴力的解法时间复杂度是O(n^2),那来看看使用哈希法进一…

mateRS能升级鸿蒙系统吗,为什么万元机华为maters保时捷玩吃鸡真么垃圾

满意答案 plae761576 2019.04.06 采纳率:45% 等级:8 已帮助:1160人 现在突然发现好多自媒体都在无下限的刷三观,为了点阅读量,想尽办法给网友们出玩《绝地求生》最低配置,最近看到一个大V自媒体竟然说显…

华为mate20 android,华为MateRS对比华为mate20RS,终于让安卓手机坐上了头等舱!

原标题:华为MateRS对比华为mate20RS,终于让安卓手机坐上了头等舱! 最近华为mate20RS正式开卖了,但是却没有现货,因此也出现了很多黄牛在加价售卖这款限量版的手机。今天我们来跟大家说说上一代的限量版华为MateRS跟最新…

华为mate40计算机,华为Mate40兼容欧米多手机电脑,秒变笔电轻办公

万众瞩目的华为Mate40将于10月22日首发,作为史上最强大的华为旗舰手机,Mate40不仅以超强性能吊足了大家的胃口,也因为或将绝版的麒麟9000芯片,充满了悲情色彩,引得众人格外关注这款新机的一举一动。 根据爆料&#xff…

华为mate40pro+和华为mate40RS保时捷有什么区别

华为mate40pro标志性星环设计,来自宇宙的设计灵感,令科技与艺术环环相扣。浪漫秘银,经典黑白,还有黄色和绿色在素皮上带来的温润触感。来,感受一下从视觉到指尖的美妙。 华为Mate40预约抢购地址:https://ww…

【Java高级语法】(六)内部类Inner Class:这可能是史上最全的关于内部类的学习资料~

Java高级语法详解之包装类 :one: 概念:two: 优缺点:three: 使用2.1 成员内部类2.2 局部内部类2.3 匿名内部类2.4 静态内部类2.5 小结:外部类访问四种内部类的特点2.6 小结:其他类访问四种内部类的特点 :four: 内部类与外部类的关系:five: 应用场景:six: …

华为20号鸿蒙系统,鸿蒙系统2.0来了,华为Mate40推迟发布

虽然华为开发者大会比不上谷歌、苹果这一量级的同类活动,但在国内依然拥有极高的关注度。 其中,在主题演讲一项,华为会给我们带来关于 HMS Core 5.0 的最新进展,更重要的是还将会揭开鸿蒙 OS、EMUI11的神秘面纱! 相信鸿…