![405ddcd92909cb42cf518a0a81c1a3d0.png](https://img-blog.csdnimg.cn/img_convert/405ddcd92909cb42cf518a0a81c1a3d0.png)
好吧,刚说了没时间,结果这个新闻让我不得不抽出时间来写几句。
更新:BuckleScript 已经带着新语法改名为 ReScript,详情见问题:
如何评价 BuckleScript 带着新语法改名 ReScript?www.zhihu.com太长不看:题图就是新的「语法选项」!
![6437244f671e02d1bc5f1cbcaa9f25b3.png](https://img-blog.csdnimg.cn/img_convert/6437244f671e02d1bc5f1cbcaa9f25b3.png)
![828bfede6a47fa0cd94c622bd66e2395.png](https://img-blog.csdnimg.cn/img_convert/828bfede6a47fa0cd94c622bd66e2395.png)
注意,因为变化比较大,目前是作为「选项」(opt-in) 发布得。
所以长什么样?
我把题图的内容复制成代码过来:
if hasEaten {
Js.log("more dessert please")
} else {
Js.log("dessert please")
}
let message = j`Hello ${userName->Js.String.toUpperCase}!`
type student<'extraInfo> = {
name: string,
age: int,
otherInfo: 'extraInfo,
}
@bs.val external window: {..} = "window"
window["addEventListener"]("focus", onFocus)
这尴尬的高亮……要不您还是看题图?
哎呀总之,有没有觉得像 JavaScript 以及其他 C-family 风格了许多?(那个长得像 C/C++ 的箭头并不是这次才有的,如果有兴趣可以搜一下 First pipe)。
我简单概括一下主要的改动:
一、终于可以完全 不 写 分 号 了!
其实以前的 Reason 语法在 95% 场合都是可以不写的,但是就是因为一些 edge cases 所以 Refmt(Reason 的格式化工具,大家都在用的 Prettier 就是借鉴自这个) 会给你加回来……现在终于可以完全扔掉分号了。
二、 泛型语法从 option(int)
变成了 option<int>
准确的术语是「参数化多态」,类型变量在定义是仍然需要 ML 风格的 '
前缀,不过应用的时候跟 Flow/TypeScript 等等大家熟悉的 C 风格更接近了。
三、操作 JS 对象的语法就像 JS 一样……
Reason & BuckleScript 在与 JS 对象「互操作」的时候通常用 OCaml 的对象语义来表示 JS 的对象[1],但是以前的 Reason 语法(尽管已经比 OCaml 要更接近 JS 了)比较谜:
type person = Js.t({.
name: string,
desc: string,
});
// 表示 hux 是一个外来的,由其他 JS 提供为 jsHux 的对象,标注类型为 person
[@bs.val] external hux : person = "jsHux";
let name = hux##name; // 读
hux##desc #= "NPC"; // 写
那么新语法呢……you ready?
type person = {
"name": string,
"desc": string,
};
@bs.val external hux: person = "jsHux"
let name = hux["name"]
hux["desc"] = "NPC"
当当当当!是不是非常迷幻,乍一看都分不出这是哪个语言了?
四、更 JS 的字符串插值和异常捕获
// before
let str = {j|hello ${name}|j}
try (foo) {
| Bar => 1
}
// after
let str = j`hello ${name}`
try foo catch {
| Bar => 1
}
五、数据容器字面量的调整
以前的 Reason 继承了 FP 语言列表(单链表)优先的做法,[1,2,3]
表示列表,数组需要表示为 [|1,2,3|]
。
新的语法则把 [1,2,3]
让给了在 JS 中更常用的数组,列表则表示为 list{1,2,3}
,这样的好处是以后可以把容器都表示为统一的风格,比如 set{...}
,map{...}
,而不用引入新的字面量。
六、这个长得像装饰器的东西长得更像 JS 装饰器了
恩,就是你看到的那个用于定义 BuckleScript 与 JS 互操作(FFI)的东西。 Reason React 定义组件也是用的这个:
[@react.component]
let make = (~name) => <button> {React.string("Hello!")} </button>;
// 现在可以省去方括号
@react.component
let make = (~name) => <button> {React.string("Hello!")} </button>;
在有参数的时候变化更明显:
[@foo bar]
变成了@foo(bar)
[%foo bar]
变成了%foo(bar)
这东西实际是 OCaml 的 extension attribute 和 extension node,不过在大部分场合你就当做 decorator 就好了。
七、其他变化还包括
if
,switch
,try
括号可选(这很 swift)- polymorphic variant(这东西你叫我怎么翻译?多态变体?)从 `foo 变成了
#foo
还有一些我就不翻译了,大家有兴趣的可以看这里有详细的语法变化介绍以及与 JS 语法对比的表格:
Reason Documentationreasonml.org![f8b7f9f2dc761e48b237d8a9d8834f7b.png](https://img-blog.csdnimg.cn/img_convert/f8b7f9f2dc761e48b237d8a9d8834f7b.png)
虽然很多时候大家都爱说「语法是一个编程语言最不重要的东西」,但是 Reason 恰恰就是一个主要关于语法以及 JS 生态的项目。我个人是从知道这个项目开始就很兴奋 Reason & BuckleScript 团队能选定「往 JS 多靠点」的方向。有了抽象与封装的方向之后 FFI 不好用以及 leaky abstraction 就都能看到解决的路径了。
对我对 Reason 之前的一些想法有兴趣的同学可以看下面这个老回答:
Reason, ClojureScript, AssemblyScript 你更看好哪门语言的未来?www.zhihu.com最后,祝贺团队能够 launch 新语法!值得一提的是这次的 parser 重写主要是由非 Facebook 员工,开源社区的核心成员 Maxim(链接为推特)贡献的。之前说能不能把 Cheng Lou 拉到知乎来说几句话估计是要食言了…… @张宏波 要不要试试?
参考
- ^https://bucklescript.github.io/docs/en/object-2