在讨论编程语言时常用的语言特性和概念

0x00 前言

这几天一时兴起,学了两眼 haskell,同时也看了不少知乎上关于各种编程语言的论战。

把一些常用到的概念捋一捋,理解和记录一下,不一定正确,只代表个人的理解。

我没搞过 PLT,对编程语言的理解比较浅薄,博文很大概率出现不少错误,多包涵。

0x01 编译型 / 解释型

编译就是通过编译把程序一次性翻译成机器语言然后执行。最常见的就是 C/C++ / go / rust 等等。

解释就是解释器一句一句来解释执行,每次执行都要有解释器的参与。常见的使用这种机制的是那些脚本语言 python / js 等等。

不过我觉得二者在实际语言中的区别没有这么分明。

比如 python 可以把脚本先搞成pyc字节码,然后每次只需要解释执行字节码,好像编译和解释的区别没有这么明显了。

还有 Java 的那一套东西,好像不能单纯的归类为解释型还是编译型,我不是很懂就不瞎说了。

0x02 命令式 / 声明式 / 函数式

命令式的语言就是给出一系列的命令和流程,告诉计算机该怎么完成。最常见的语言基本都是这种吧。

声明式语言就是告诉计算机想要什么,不用管怎么做到的,网上说 SQL, HTML 就属于这种。我也不知道说的对不对,不瞎白话了。

函数式语言就比较神奇,感觉大学阶段就从来没人教过。主要是把函数当做最重要的部分,把运算过程写成一系列嵌套的函数调用。其中比较常见的比如 haskell, lisp。我还没用函数式语言写过啥真正的程序,感觉理解的还不到位。

0x03 面向对象 / 面向过程

这俩主要是编程的思路和设计上的不同,面向对象这一块学校里是教了又教(why???)。

引用一下网上的说法:

面向对象系统将数据和代码通过“对象”集成到一起,而不是将程序看成由分离的数据和代码组成。 对象是数据类型的抽象,它有状态(数据)和行为(代码)。

在编程语言上的体现主要是对面向对象的支持程度是不是好,比如继承、封装、多态啥的。

至于这两种范式各有什么优缺点,我觉得以我目前的水平和经验还说不好这一块。

0x04 静态类型 / 动态类型

静态类型就是编译的时候会进行类型检查。一般写代码的时候要指定变量的类型。比如 C/C++ Java

而动态类型则在运行时才会进行类型检查。写的时候不用指定类型。比如 python / php

0x05 弱类型 / 强类型

弱类型语言在不同类型变量运算时会有隐式的类型转换,比如 C/C++, PHP

强类型语言不容忍隐式类型转换,比如 python, str + int 会报错的

0x06 传值 / 传引用 / 传指针

这篇文章说的比较具体。

如果讨论实际的语言:

  • C++ 三种方式都有,用哪种方式可以自己选。

  • python 一切都是对象,网上一般认为是传引用。然而 stackoverflow 上说人家叫 call-by-assignment

  • java 好像比较复杂,有人说基本类型传值,对象类型传引用。还有人说java只传值,对象类型传递的是类似指针的东西,本质还是传值。

总之,对我来说在实际使用中只要不会因为不了解这个而在函数中改了可变对象还找不到bug就行。XD

0x07 类型推导

简单说就是编译器能够推导出运算的结果的类型,比如 go 里面的 := 还有 C++11 里面的 auto

我还没有真正学习过类型系统,不好细说。

0x08 泛型

泛型就是让变量的类型可以参数化。

比如C++写一个数组排序,用模板实现就可以不必为每一种类型都抄一遍一样的代码。

java里的泛型和C++的模板是不太一样的。具体哪不一样呢,我也没怎么用过,就不细说了。

0x09 垃圾回收

垃圾回收就是释放不用的动态内存空间。

具体到语言,比如,C语言是没有的,需要自己管理动态内存。更高级一点的语言一般都带有这种机制,实现的方式也各不相同。

0x0A 总结

我觉得对于我来说,研究编程语言的目的还是在于能选择适合的语言,写让自己得更舒服,同时不会因为不理解语言的特性而写出错误代码。

这个领域我接触的还很少,毕竟我不是专门研究 PLT 的。就算不专门去研究,我想在使用中也能不断加深理解的吧。