How typed C++ is, and why it matters

这是我第三次参加在巴黎举行的软件技术交流会。就像第一次和第二次一样,这又是一次极好的经历。

这个聚会让参与者共同选择要讨论的主题。在那里,为了指出语言之间的一些差异,我建议作为一个小组来面对房间里的人所知道的各种语言(工作人员并不是特别面向c++)。重点是发现其他语言采用的新方法,通过比较,更好地理解我们自己的语言。

这段经历让我对c++有了更深入的了解,所以我想和大家分享一下在这次活动中交换的心得。

辩论的主要内容是关于类型(type)的主题。在c++中,我们使用类型作为一种强大的工具,使代码更有表现力,就像使用强类型一样。

但是,虽然一些常见的语言,如c++和Java,被归类为有类型的语言,但其他一些语言——同样常见——却不是,如JavaScript或Python。有些语言——如Haskell或Idris——甚至比c++更为类型化。稍后再详细介绍。

一般来说,使用强类型语言编程的人无法想象其他人如何能过上体面的生活,反之亦然。我认为这是一种错误的方法: 有很多人用这两种语言编写代码,所以这两种语言至少都有优点(可能也有缺点)。

而且我相信,理解你的语言在类型能力范围内的位置将为你提供一个丰富的视角。

所以让我们开始吧,就像你在那里一样!

我们将从类型化的优点开始。

Typing brings protection

类型化的第一个优点深深根植于c++程序员的思维模式中: 类型化可以防止程序员犯一大堆错误。这些错误本质上在于将错误的对象传递给错误的上下文

在c++中,类型由结构体、类或基本类型(int、double、char等)来体现。它代表了一个概念,该类型的所有对象都按照这个概念建模。例如,int为一个整数建模,Employee表示职员中的某个人,Date表示时间中的某个时刻。

通过声明在特定的上下文中期望的类型——比如函数的参数——编译器确保传递给这个上下文中的对象类型是期望的类型。有些语言试图在这个方向上走得更远,通过使用类型系统来防止意外状态的发生。关于Elm语言的视频Making impossible states impossible被提出来说明这一点。

因此,语言中的强类型通常会减少必要的测试数量。由于有些事情不可能通过语言构造产生,所以没有必要用测试来确认。在c++这样的类型化语言中,你不会编写一个将int传递给期望std::string的函数的测试,以确保其行为正常,因为这样的代码将被编译器完全拒绝。

Typing brings expressiveness

有人在辩论中提出了一个有趣的问题:类型是否为编译器服务?

答案是:不,类型可以帮助人类开发人员在他们的程序中看得更清楚。当然,编译器知道类型并根据它们进行检查,但这仅仅是为了防止人类被代码变得越来越复杂而不堪重负。想想看,一旦源文件被编译成机器码,剩下的就只有0和1了。这些类型早就消失了。

事实上,类型可以作为文档的另一种形式。例如,如果考虑一个函数接受一个FirstName类型的对象和一个LastName类型的对象,并返回一个年龄,那么你马上就会强烈地感觉到这个函数以某种方式检索了一个人的年龄。除了函数原型所涉及的类型之外,你不需要任何其他信息就可以理解这一点。

有些语言更进一步,定义了可以包含任何类型的函数原型。例如,考虑一个函数,它可以接受任意类型A的对象作为参数,并返回一个类型A的对象。乍一看,肯定有大量的函数适合这个原型。但结果是只有一个:恒等函数。这是类型在原型中提供信息的一种令人惊讶的方式。本·迪恩在CppCon上的“有效使用类型”演讲中提供了更多关于这一点以及这在c++中如何有用的信息。

与类型类似的一个有趣的例子是现实生活中的对象是什么样子的。事实上,它们的外观提供了有关它们是什么以及如何使用它们的信息。代码中的类型也有点类似,因为它们是它们所建模的对象的固有组成部分,它们传达有关它们的意义和有用信息。

为了更深入地了解这种思维方式,我推荐了这本书:《The Design Of Everyday Things》。这不是第一次在开发人员的讨论中提到这本书,现在它肯定在我的阅读列表中。当我读到它的时候,你可以指望我写一篇专门的文章来分享它的相关见解,使代码更有表现力(如果有的话)。

Isn’t there anything wrong with typing?

到目前为止,只提到了类型的积极方面。但是它不会带来任何负面影响吗? 即使我是一个成熟的c++程序员,我也不相信类型系统全是好的。我的意思是,有那么多的人和那么多的代码使用弱类型语言,这样做肯定有一些有趣的方面。所以我问了这个问题:你觉得类型有什么烦人的地方?下面是讨论的结果。

弱类型语言的第一个好处是它们不受类型系统的限制,提供了一种自由的感觉。这使类型化语言变得更加令人不快和复杂。

在弱类型语言中开发速度更快。快得多。不过我还没有找到一个具体的例子来说明这一点。

使用类型化语言,需要在某些时候编写强制类型转换,即使在确切知道代码中需要什么类型的情况下也是如此。有人举了一个系统调用的例子来说明这一点。

最后,如果能够对提供特定功能的对象执行操作,而不管对象的类型是什么,这是很有用的。这就叫做“鸭子类型”(因为如果一个东西跑起来像鸭子,飞起来像鸭子,叫起来像鸭子,我们也可以把它当成鸭子来用)。这正好对应于c++隐式接口,这是模板的当前状态。

To Type or Not To Type

所以类型有利有弊。有没有一种方法来决定什么时候类型系统更合适,什么时候不合适?

有人提出了一个有趣的观点。类型带来保护和清晰,但也有一些麻烦。因此,这适用于复杂的应用程序,比如大型软件。对于较小的任务,比如脚本的例子,输入不值得这么麻烦,弱类型语言就可以了。一个令人信服的例子是脚本语言往往是非常弱的类型化语言。

这一观点引起了我的共鸣,但最终遭到了反对,因为它可能涉及到抽样偏差。事实上,如果你从事过涉及c++的大型项目,那么很容易认为类型是必要的。但是当你思考这个问题的时候,你会发现也有很多非常大的项目是用弱类型语言编写的,而且仍然很成功!例如,Facebook是用PHP编写的。所以我不知道该怎么思考这个问题。

C++ in the midst of all this

下面是软件工艺聚会的组织者之一Xavier Detant向我解释的,他在软件开发方面有非常丰富的知识。

在c++中,类型系统是如此重要和有用,以至于我们可能认为c++是一种真正的强类型语言。但事实证明,有些语言甚至更多地使用它们的类型系统。这里有两个:

  • Haskell:与c++相比,Haskell可以说是强类型的,因为类型包含了更丰富的信息。代数数据类型很好地说明了这一点,代数数据类型包括用几种不同的形式描述一个类型。例如,树可以是一个节点,也可以是一个带有一个值和两个树作为子节点的树。采用树的函数对该类型的两种形式进行模式匹配。更多关于如何将其应用于c++的内容,请参见上面引用的Ben Deane的演讲。
  • Idris: Idris是一种非常强类型的语言,甚至比Haskell更强。它在语法上有很多共同之处,但是类型系统的发展潜力更大。Idris使用依赖类型,这意味着类型的选择,如函数的返回类型,可以由值决定。如果你对此感兴趣,可以看看这篇文章。我必须承认,我还没有完全理解这一点(目前我所理解的是这个概念),但我认为这种编程方式一定有一些有趣的收获。当我讲到它的时候,你肯定会有一篇关于如何使用它们来编写富有表现力的C++的新文章!

原文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值