Saya Lang: Optional

Saya 新增了 Optional 类型,同时带来一些新语法。

let value: i64 = 1337;
let opt_n: ?i64 = none;
let opt_s: ?i64 = some value;

if let some v = opt_s {
   //  ...
}

语法

我深知语法只是次要的部分,可设计语法的过程却很有趣。

I also regard syntactical problems as essentially irrelevant to programming languages at their present stage of development. In a rough and ready sort of way it seems to me fair to think of the semantics as being what we want to say and the syntax as how we have to say it. In these terms the urgent task in programming languages is to explore the field of semantic possibilities. When we have discovered the main outlines and the principal peaks we can set about devising a suitably neat and satisfactory notation for them, and this is the moment for syntactic questions.

— Christopher Strachey, Fundamental Concepts in Programming Languages (1967; published 2000), p. 12.

值

纠结了很久如何表示可选类型的值(类似 Rust 中的 Option::Some(v)),思来想去,最后决定加入 some 和 none 关键字,some 当作前缀运算符解析,看起来就像这样:

let value: i64 = 1337;
let opt_n: ?i64 = none;
let opt_s: ?i64 = some value;

不算非常清晰,some 和 none 像是普通变量,但也好过 some(v),那样会让人误会为某种函数调用11.Rust 的 Some(v) 本身就可以看作枚举的构造函数,所以倒是合理。

也考虑过 Some v,那样可以蹭上 Rust 的语法高亮。它长得很像结构体名称,saya 里基本上只有结构体和自定义类型才用大驼峰命名,可能混淆。并且,saya 从来没有在解析器里按大小写区分关键词,就不开这个头了。

前两天看到 lobste.rs 上对语言设计的一串讨论,提到 bare keywords,原文章作者认为关键字应该带有标识(Sigil),以便清晰地区分关键词和其他标识符22.他的出发点是关键词拓展时的向后兼容,另外的话题。。

$let value: i64 = 1337;
$let opt_n: ?i64 = $none;
$let opt_s: ?i64 = $some value;

$if $let $some v = opt_s {
   //  ...
}

或者反过来,就像 PHP 那样:

let $value: i64 = 1337;
let $opt_n: ?i64 = none;
let $opt_s: ?i64 = some $value;

if let some $v = $opt_s {
   //  ...
}

前者麻烦点,后者写起来更轻松,怎样都比不带标识的 some 清晰,或者说“准确”33.为了对比,我特意关闭了上面三个代码块的高亮,阅读第一段代码的心智负担确实更大,但这是没有高亮区分的情况,是能被缓解的。。

其实我最早还试过 stropping 的方案,给 some 单独加 . 前缀,看起来还不错,只不过 . 前缀没有融入整个语言,就做罢了。

let a: ?i64 = .none;
let b: ?i64 = .some 1337;

类型

Optional 类型使用问号 ? 前缀加上任何类型名称来表示,与 Zig 类似。个人认为 ?T 比 T? 更清晰,「此类型可选」的信息放在更前面,更容易识别。

Optional 类型的嵌套就是在前缀追加 ?,比如表达「是否选中表格单元格」可以写为 ??i64。这个例子举得有些晦涩,拆开就好理解了:

type Value = i64;
type Cell = ?Value;
type SelectedCell = ?Cell;
// type SelectedCell = ??i64;

也曾考虑过关键词前缀,比如 opt i64,不过这样就会出现:

let selected_cell: opt opt i64 = some none;

吵到我的眼睛了。

解包

Optional 类型是直接实现的语言内置特性,不是通过和类型(sum types)实现的,现阶段为它引入 match 为时过早。因此这次只加入最简单的解包与绑定语法,照抄 Rust 的 if let PAT = EXPR { BODY }。

let total = 100;
let discount = some 20;

if let some amount = discount {
    total = total - amount;
}

类型检查

todo!()

代码生成

todo!()

1

Rust 的 Some(v) 本身就可以看作枚举的构造函数,所以倒是合理

2

他的出发点是关键词拓展时的向后兼容,另外的话题。

3

为了对比,我特意关闭了上面三个代码块的高亮,阅读第一段代码的心智负担确实更大,但这是没有高亮区分的情况,是能被缓解的。

Copyright © 2024 13m0n4de · CC BY-NC 4.0