正文

许多人也许会注意到一个现象,那就是在一些现代编程语言(当然,并不是指“最近出现”的编程语言)中,自增和自减运算符被取消了。也就是说,在这些语言中不存在i j--这样的表达,而是只存在i = 1j -= 1这样的表达方式了。本回答将从设计哲学这个角度上探讨这一现象产生的背景与原因。

严格来说,说"i 正在消失"也许有失偏颇,因为主流编程语言中似乎只有Python、Rust和Swift不支持自增自减运算符。

当我第一次接触Python时,这也曾令我感到困惑。我曾经有兴趣地搜索了很多相关的回答和文章,但都没有得到满意的答案。如今数年过去了,我尝试重新思考这个问题,并给出我的答案。

请注意,本文仅“从设计哲学上”讨论这一问题,不会特别涉及语言本身的性质。例如在Python中,不提供自增自减运算符很大一部分原因是由于其整数类型为 Immutable 的,但这并不是“从设计哲学上”的讨论,因此本文不会包含相关内容。

为什么会存在自增自减运算符?

起源

维基百科指出,自增和自减运算符最早出现在B语言(即C的前身)中。B语言的发明者与C语言的发明者相同,也是K&R,其中Ken Thompson最早在B语言中引入了自增与自减运算符。因此也常常有人不太严谨地说“自增自减运算符最早起源于C”,事实情况虽然有些出入,但也差不了太多。

B语言的语法与C高度相似,最大的不同可能在于B是无类型的。不过,这里不太多介绍B语言,否则就偏离主题了。这里所要强调的只是自增自减运算符最早的起源。

关于为什么B语言中引入了自增自减运算符这个问题众说纷纭,Ken Thompson也从未公开表示过自己当初为何创建了这两个运算符。然而,有一个误解需要澄清,即这两个运算符的引入不可能是对应于汇编语言的INCDEC指令。事实上,B语言的另一位创造者(当然,也是C语言的创造者)Dennis M. Ritchie曾在其回忆"The Development of the C Language"中指出:

……Thompson went a step further by inventing the   and -- operators, which increment or decrement; their prefix or postfix position determines whether the alteration occurs before or after noting the value of the operand. They were not in the earliest versions of B, but appeared along the way. People often guess that they were created to use the auto-increment and auto-decrement address modes provided by the DEC PDP-11 on which C and Unix first became popular. This is historically impossible, since there was no PDP-11 when B was developed.  The PDP-7, however, did have a few 'auto-increment' memory cells, with the property that an indirect memory reference through them incremented the cell. This feature probably suggested such operators to Thompson; the generalization to make them both prefix and postfix was his own. Indeed, the auto-increment cells were not used directly in implementation of the operators, and a stronger motivation for the innovation was probably his observation that the translation of  x was smaller than that of x=x 1.

文中的说法有些模糊,仅指出自增自减运算符不可能是产生于PDP-11的auto-increment和auto-decrement地址模式(因为B语言发明时这台机器甚至都不存在),然而并未指出其是否对应于汇编语言中的INCDEC。为了验证这一说法,我找到了文中提到的PDP-7的指令集,的确不包含INCDEC指令。为了严谨起见,我还查了一下PDP-7的汇编手册,也没有找到相关指令。这证明了自增自减运算符的发明不可能是由于其直接对应于汇编语言中的INC和DEC指令

顺带一提,为了考证INC和DEC汇编指令的最初出现时间,我找到了1969年版的PDP-11 Handbook, 其中指出了INC和DEC是在PDP-11中被新引入的汇编指令(截图中没包含DEC,但手册后面有包含这条指令):

PDP-11 Handbook, 1969, Page 34

PDP-11的正式发布时间是1970,而B语言的诞生时间是1969。除非Ken Thompson参与了PDP-11的早期开发工作,否则自增自减运算符的灵感不可能源于INCDEC汇编指令。当然,正如Dennis Ritchie指出,早在PDP-7中就已经出现了auto-increment memory cells,很可能是它启发了Ken Thompson引入自增自减运算符

另一个能够反驳“自增自减运算符直接对应于汇编指令”的事实是,B语言最初并不能直接编译成机器码,而是需要编译成一种被称作“线程码(threaded code)”的东西(原谅我找不到合适的翻译) 。既然最初都无法直接编译成机器码,那就更没有这种说法了。

所以说,自增自减运算符最初出现的原因可能非常简单——当年机器字节很珍贵,而 x能比x=x 1或x =1少写一点代码,在那时候能少写一点代码总是好的——于是自增自减运算符出现了

提高程序运行效率?原子性?

好吧,虽然上面已经严肃地论证了自增自减运算符的出现与PDP-11的ISA没关系,但K&R不过是C的创始人,他们懂什么C语言(雾)?K&R之后C语言的各种语法都被玩出花来了,恐怕他们也想不到C语言后续的发展。自增自减运算符到底会不会被编译成INCDEC,还得看现代的各种编译器。下面我在Ubuntu 22.04下将相关的C代码编译,然后反汇编,看看i 是否会被编译成INC,以验证“自增自减运算符能够提高程序运行效率”的逻辑是否成立。

下面是测试程序:

// incr_test.c
#include <stdio.h>
int main(void)
{
    for (int i = 0; i < 5; i  )
    {
        printf("%d", i);
    }
    return 0;
}

然后运行gcc,默认不开启优化:

gcc -o incr_test incr_test.c

然后运行objdump反汇编:

objdump -d incr_test.c

下面展示相关汇编代码(我所使用的是x86-64平台),已剔除无关代码:

0000000000001149 <main>:
    1149:       f3 0f 1e fa             endbr64 
    114d:       55                      push   %rbp
    114e:       48 89 e5                mov    %rsp,%rbp
    1151:       48 83 ec 10             sub    $0x10,%rsp
    1155:       c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%rbp)
    115c:       eb 1d                   jmp    117b <main 0x32>
    115e:       8b 45 fc                mov    -0x4(%rbp),                    

Python Ruby 等语言弃用自增运算符原因剖析的更多相关文章

  1. ios – ipatool无法使用bitcode构建(xcode 7.1.1)

    在日志中我发现的是:有小费吗?解决方法在管理器上单击“分发应用程序”后,我在XCode10.1上遇到了同样的问题.在我的情况下,这是因为我从我的终端调用XCode并且rvm配置了不同的ruby版本.运行rvm系统为我修复了它.

  2. XCode 3.2 Ruby和Python模板

    在xcode3.2下,我的ObjectiveCPython/Ruby项目仍然可以打开更新和编译,但是你无法创建新项目.鉴于xcode3.2中缺少ruby和python的所有痕迹(即创建项目并添加新的ruby/python文件),是否有一种简单的方法可以再次安装模板?我发现了一些关于将它们复制到某个文件夹的信息,但我似乎无法让它工作,我怀疑文件夹的位置已经改变为3.2.解决方法3.2中的应用程序模板

  3. ios – 为具有多个目标和不同平台的项目编写Podfile

    如何让CocoaPods成功整合到我的项目和iOS/Mac目标?我已经阅读了Podfile文档,但发现它在这方面缺乏.解决方法得到它了!从我的每个目标和运行的pod安装中删除libPods-xxxx.a文件,再次执行了我的目标集成.

  4. ios – 从Xcode Cocapods插件运行pod安装

    我正在尝试从Xcodecocoapodsplugin运行pod安装命令.当我运行update/installcocoapods命令我得到一个错误:这是奇怪的,如果我去终端中的目录,并运行一个pod安装我没有问题.要注意的是,错误是指Ruby2.0.0,而当我从终端中的目录运行ruby-v命令时,我得到(ruby1.9.3p327(2012-11-10修订版37606)[x86_64-darwin1

  5. Swift基本使用-函数和闭包(三)

    声明函数和其他脚本语言有相似的地方,比较明显的地方是声明函数的关键字swift也出现了Python中的组元,可以通过一个组元返回多个值。传递可变参数,函数以数组的形式获取参数swift中函数可以嵌套,被嵌套的函数可以访问外部函数的变量。可以通过函数的潜逃来重构过长或者太复杂的函数。

  6. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  7. Swift中实现ruby中字符串乘法倍增的功能

    hopy;)我们知道在ruby中对于字符串类型我们可以用乘法生成一个指定数量重复的字符串:但在Swift中String默认是没有该实现的,不过要想实现该方法也十分之简单,只要定义一个*法操作符就可以了:

  8. Swift、Go、Julia与R能否挑战 Python 的王者地位

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  9. 红薯因 Swift 重写开源中国失败,貌似欲改用 Python

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  10. 你没看错:Swift可以直接调用Python函数库

    上周Perfect又推出了新一轮服务器端Swift增强函数库:Perfect-Python。对,你没看错,在服务器端Swift其实可以轻松从其他语种的函数库中直接拿来调用,不需要修改任何内容。以如下python脚本为例:Perfect-Python可以用下列方法封装并调用以上函数,您所需要注意的仅仅是其函数名称以及参数。

随机推荐

  1. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  2. python数学建模之三大模型与十大常用算法详情

    这篇文章主要介绍了python数学建模之三大模型与十大常用算法详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感想取得小伙伴可以参考一下

  3. Python爬取奶茶店数据分析哪家最好喝以及性价比

    这篇文章主要介绍了用Python告诉你奶茶哪家最好喝性价比最高,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

  4. 使用pyinstaller打包.exe文件的详细教程

    PyInstaller是一个跨平台的Python应用打包工具,能够把 Python 脚本及其所在的 Python 解释器打包成可执行文件,下面这篇文章主要给大家介绍了关于使用pyinstaller打包.exe文件的相关资料,需要的朋友可以参考下

  5. 基于Python实现射击小游戏的制作

    这篇文章主要介绍了如何利用Python制作一个自己专属的第一人称射击小游戏,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起动手试一试

  6. Python list append方法之给列表追加元素

    这篇文章主要介绍了Python list append方法如何给列表追加元素,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  7. Pytest+Request+Allure+Jenkins实现接口自动化

    这篇文章介绍了Pytest+Request+Allure+Jenkins实现接口自动化的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. 利用python实现简单的情感分析实例教程

    商品评论挖掘、电影推荐、股市预测……情感分析大有用武之地,下面这篇文章主要给大家介绍了关于利用python实现简单的情感分析的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

  9. 利用Python上传日志并监控告警的方法详解

    这篇文章将详细为大家介绍如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务,感兴趣的小伙伴可以了解一下

  10. Pycharm中运行程序在Python console中执行,不是直接Run问题

    这篇文章主要介绍了Pycharm中运行程序在Python console中执行,不是直接Run问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

返回
顶部