[翻译]编译器(4)-语言设计

原文在此。另外推荐阅读王大师的“设计和开发 Yin 语言”,你会看到另一个完全不同的语言设计思路
————翻译分隔线————

编译器(4)-语言设计

第一部分:介绍
第二部分:编译、转译和解释
第三部分:编译器设计概览

在第一部分概述了这一系列文章将介绍的内容。在第二、三部分粗略的浏览了计算机语言编译的各个步骤。

在本文中,将会比上几篇概述介绍的内容略微详细一些。我将讨论语言的规格说明书。

语言设计概述

我刚刚是不是说我将不再进行太多的概述?一转身,我就变成了一个卑鄙无耻的骗子。

为了让我们更快的进入编码阶段,我已经尽量简明扼要的进行介绍。同时我也希望明确一点,这是一个非常不完善的语言设计。计算机语言设计是一个你可以为之奋斗一生的话题。我无法为你提供在 Calc 用到的支撑设计的理论。我不会对此进行探讨。

事实上,我只会告诉你语言规格说明书是什么。

我得承认 Calc 算不上一个真正的编程语言。它的出发点是构建一个基础的用于教学的编译器,并且作为 Calc 的未来版本的基石,在将来的系列博文中使用。

语言设计很难,非常难。说“我想要这个特性,那个特性,和另外那些特性。”很容易。为什么?用于什么目的?如何让它匹配设计?它会让用户迷惑吗?是否有必要?谁是你的目标用户,还有他们想要或者需要这个特性吗?

循环

即使有丰富的经验,这些也不是容易回答的问题。有一些特性,例如循环结构,看起来似乎不需要怎么思考,但是真得是这样?来看看最常见的两种循环结构:for 和 while。

几乎所有的计算机语言都设计了一些用于循环的方法,不论是用于跳转的 goto 语句还是很常见的 for 和 while 循环。递归是另一种样式的循环。不过最流行的应当是 for 和 while 了。

第一个问题,首先是:为什么?

好吧,我们想要重复一些动作。OK,相当简单。

for 和 while 都需要一个退出条件来完成。通常这些条件是与逻辑 true 和 false 关联的。两种不同的编写方式:

while(condition) do { action }

for (start; condition; increment) do { action }

为什么?在最初的时候,我想这些循环的的逻辑是出于不同的考虑。然而 Go 开发者看到了两种结构中的共性,并问了自己这个问题:“为什么?”

为什么要有两种关键字,两个保留字来实现一个本质上一样的事情?用一种循环结构和唯一的保留字来取代这两个,虽然可能在分析的时候会更复杂,但是对于终端用户来说不是更好吗?

Go 开发者选择了更短的那个作为关键字。我还觉得这个选择直觉大于理论支撑。“for (条件) do { 操作 }”很直观。通过向一个我们已经逆来顺受很久的简单的认知,瞬间,我们的语言变得简单和清晰。当一个就能满足,谁还会用两个呢?

取舍

总是会有取舍。复杂或是简单。速度或是便利。

循环的决策所带来的成本是在解析时稍稍复杂了一些。开发者有意识选择让 for 语句解析更加困难来为程序员提供生产力上的巨大的改进。

泛型是一个热门话题。Go 并未提供任何关于泛型的特性。为什么?

泛型仅仅是一种取舍,并且我无法向你解释清楚。你最好是在 golang 的邮件列表里做一些研究,并看一下 FAQ

最终结果是你需要决定你需要什么。你是想要一个简洁并且平凡的语言,还是一个复杂的,可以做任何事情的语言?为什么你做了这样的选择?

一个特性也出现在其他语言中并不意味着它必须存在。while 循环就是相当好的例子。

在 Go 中,switch 比它在像 C 这样的语言中的功能丰富得多。基本观点是在无须让程序员增加太多认知复杂度的前提下提供强有力的功能。

类型系统

动态或静态?强类型还是弱类型?直白还是隐含?

个人来说,我更喜欢强类型、静态语言。我希望在无须额外任何操作,就能确定我得到的就是我想要的。

一个类型能够或者应该转换吗?一个浮点数能是一个整数吗?一个字符能是浮点吗?字符串是什么?

在数组上进行边界检查?slice 呢?

指针还是可取地址的变量?变量是引用传递还是值传递?

就像我说过的,一些看起来很简单的东西可以非常非常快的变复杂。

总结

我突然对许多语言都充满的尊敬。诚实来说,我不喜欢 Java。我了解它的威力,但是用它写代码感觉就像是跟驴子一起编程。虽然这样说,但是我不得不佩服设计者。我钦佩他们已经做到并完成的。我不得不钦佩这可能是最好的、或者说唯一的做法,回头路永远都是个坏主意。Java 工作良好,并且无数程序员在使用它。你不得不对此表示敬意。

你可能会做一个糟糕的设计选择,无论你认为你有多聪明。从 2011 年初,当我对 Go 语言关注开始,我就加入了 Go 邮件列表,并且见证了这个语言演化发展直到 1.0 发布。曾经许多围绕着语言设计的争论,将来也会持续下去。语言设计是相当困难的,而你的决策不会让每个人都开心。

就如我之前说的,语言设计是一个巨大的话题。我认为,许多语言成为取悦所有人的受害者。它们的工具箱已经满得溢了出来。其他一些语言划了一条不可逾越的底线,即使面对压倒性的证据证明其必要性的时候。这两种策略将用户踢走了。

你需要决定选择哪个阵营以及为什么这么选择。

Join the Conversation

1 Comment

  1. 国外另有牛人在写 Ruby 编译器系列,比这个系列更偏动手,第一篇就有汇编生成了。地址在这里,我觉得可以作为这个系列的进阶。

Leave a comment

Your email address will not be published. Required fields are marked *