d的和类型

原文

理由

和类型(sumtype)在许多语言中都是有用和流行的.类型与证明是有用和流行模式匹配配合得很好.与C风格无标签联相反,和类型主要特征是保证安全访问成员.并保证处理和类型的所有情况.Sumtypes是可靠避免常见编程的在不先检查值是否无效下就访问值的错误.当函数需要指示有错误及返回错误无效时,Sumtypes异常的替代方法.

先前工作

std.和类型

同D受限的表现力工作时,它是出色的实现,但因为要用类型来指定和类型的用例,有限制.这里

1,std.和类型不能包含普通枚举成员
2,std.和类型无法优化不存在的标签,如,当有:

enum Option { None, int* Ptr }

3,如果模式匹配中未考虑所有情况,则不会产生编译时错误,而是抛异常
4,无法提取子匹配赋值给其他变量
5,仅按类型而不是按值匹配
6,整(int)指针不能同时且安全的在和类型中.
7,不能有属于同一类型的两个字段声明
swift
rust
c++

描述

类型有一组独特命名成员.任一时候,只能一个这些成员.由叫标签隐藏字段指定是哪一个.
类型具有枚举,构和联的特征.因为可包含一组命名整数值,像枚举.因为它包含一个标签和一个类型的所有成员两个字段,又像一个.又因为所有成员共享第二个字段,又像一个.
类型大小是:标签大小+最大成员+对齐填充.
字段声明成员函数受联的成员函数限制.
类型的成员可有由实现按顺序赋值的整数值,程序员赋值唯一整数值,也可是指定类型值.

和类型的第一个成员默认是它的初值.可复制和类型.
和类型的成员不能有复制构造器,后复制(postblit)析构器.
和类型枚举成员类型是可表示所有枚举成员值最小类型.如果没有负值,则用类型.
和类型特例允许使用非空针.
引入了新QueryExpression式,可查询和类型是否包含指定成员.

语法

SumTypeDeclaration:
    `和类型` Identifier SumTypeBody
    SumTypeTemplateDeclaration

SumTypeBody:
    `{` SumTypeMembers `}`

SumTypeMembers:
    SumTypeMembers
    SumTypeMember `,`
    SumTypeMember `,` SumTypeMembers

SumTypeMember:
    EnumMemberAttributes SumTypeMember
    EnumMember
    FieldDeclaration

EnumMember:
    Identifier
    Identifier = AssignExpression

FieldDeclaration:
    Type Identifier
    Type Identifier = AssignExpression

SumTypeTemplateDeclaration:
    `和类型` Identifier TemplateParameters Constraint (opt) SumTypeBody

QueryExpression:
    `?` PostfixExpression `.` Identifier

替代语法

和类型 Option(T) = None | Some(T);

对比:

和类型 Option(T) { None, Some(T) }

示例

函数可返回两种类型,一种表示错误,另一个是结果.可实现为:

和类型 Result
{
    Error,
    int Value
}

Result func()
{
    Result res;  // 初化为Result.Error
    if (things went well)
        res.Value = 25; // 非错误结果
    return res;
}

void plugh()
{
    Result ret = func();
    if (?ret.Error)
        printf("中错误\n");
    else
        printf("结果是%d\n", ret.Value);
}

如果在Kod中存储,则只能(通过运行时检查标签)提取.对整*来说也一样.因此,虽然整*占用相同存储空间,但不能混为一谈.Kod的大小会占用2个整,一个是标签,一个是x|y.

enum Kod
{
    int x;
    int* p;
}

模板

可像声明一样参数化和类型:

enum Option(T)
{
    int Integer,
    T Other,
}

查询式

如果和类型包含指定变量,查询式返回,否则.

x = Xyzzy.busy;
if (?x.busy)
    writeln("busy");
else
    writeln("not busy");

安全

想法是避免访问(由标签指定的)不在和类型中值.

写入和类型是安全的,因为它会用新值重写现有值.

enum Xyzzy { busy, int allow, int* ptr }

Xyzzy x;
x = Xyzzy.busy;     // 好
x = Xyzzy.allow(3); // 好
int i;
x = Xyzzy.ptr(&i);  // 好

只能读取实际在和类型中的值:

Xyzzy x = Xyzzy.busy;
Xyzzy y = x.busy; // 好
y = x.allow;      // 运行时错误
y = ?x.allow ? x.allow : Xyzzy.busy;
x = Xyzzy.allow(3);
y = x.allow;      // 好

指针和引用

对调用和类型成员函数,和类型类型成员指针和引用是很有用的.会造成以下问题:

int i;
Xyzzy x = Xyzzy.allow(3);
int** p = &x.allow;  // 好
x = Xyzzy.busy;
*p = null;      // 出错

目前最务实方法是,在@safe中,简单禁止使用和类型成员的地址或引用.

隐式转换和转换

和类型不会与其他类型隐式互转换.

是式(IsExpressions)

使用sumtype关键字扩展是式来标识和类型.

混杂名

添加TypeSubtype.

TypeSubtype:
    `No` QualifiedName

非空针特例

可用sumtypes来创建非null指针.如,以下在Null成员和Ptr成员之间共享存储.因此,不检查Null就无法提取Ptr,默认初化指针(Pointer)Null.

和类型 Pointer
{
    Null,
    int* Ptr,
}

Pointer nnp;   // 默认初化为Pointer.Null
if (?nnp.Null) printf("null pointer\n"); // 好
int* p = nnp.Ptr;  // 运行时错误
int i;
nnp.Ptr = &i;
p = nnp.Ptr; // 好

这里问题是:

nnp.Ptr = cast(int*)null;
p = nnp.Ptr;  // 编译, 但置p=null

解决方法识别,是0成员+指针形式.然后,和类型用指针合并标签.因此如果赋值空针和类型,则和类型Null打标签.禁止空针的语言不需要该特例.

DMD中的实现

和类型共享enums,structs,和union的特征.按其中之一的和类型实现可能太复杂,不值得.因此,为它构建新类型和新声明.

但由于可按枚举实现只有枚举成员的和类型,编译器应重写它.同样,只一个字段和类型声明应按构重写(并省略标签).此外,可按指针重写值为0枚举成员及1个指针的字段声明的和类型.

匹配模式

适合访问和类型的模式匹配语句是另一个DIP的主题.

未来方向

除了枚举成员和字段声明外,还可添加元组声明.

中断和弃用

已在火卫一中按模块名和类型.必须:
0,查找其他关键字
1,更改std.sumtype模块名
2,使用环境相关关键字

posted @   zjh6  阅读(19)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示