当前位置: 首页 > 科技观察

为什么我们需要更好的编程语言?

时间:2023-03-13 19:09:50 科技观察

我总是告诉人们:“编程是惊人的。”只要你有任何想法,你就可以编写软件,它就会发生。这是非常真实的。与首先需要构建整个工厂的实体构建不同,软件相对容易扩展。你可以找到所有已经编译好的组件,而且它是免费的,拿去使用就可以了。一段代码一旦建立起来,不用花钱就可以重复使用无数次。听起来不错。但有时情况并非如此。编程带来的惊喜只是暂时的。创建大量代码后,在编写代码的过程中会不断遇到令人困惑的错误。一旦你习惯了特定语言和框架的模式,一旦你需要第二天性来掌握所选语言的不自然语法,编程的伟大之处就不复存在了。更不用说我们有无数种不同的编程语言。每当开发人员对特定语言的语法感到沮丧时,他们就会想“为什么我们不能创建一种新语言来解决这个问题?”有的会,幸运的是通过自然选择淘汰了很多不好的语言(有时是有意外的,像PHP到今天还存在)。一旦一种新语言开始在一组开发人员中流行起来,恭喜——现在有一个新的开发人员社区共同努力使该特定语言发展壮大。每种新语言的诞生所带来的创新使我们每个人都受益。但有时也有不利的一面。有些人可能已经写了一些非常有用的开源JavaScript库,但是Python开发人员却完全无法使用。他们必须自己编写一个Python版本的库,或者用JavaScript重写所有代码。然后想想今天有多少种语言和框架。如果你不觉得这很可笑,那只能说明也许你从事软件开发的时间太长了,已经习以为常了。语言是由什么组成的?编程语言在语法、语义和标准库三个方面差异很大。是的,我知道,我把它们简单化了,但让我解释一下。1.语法如果你不遵循语法,那么你会在编辑器中看到各种波浪形的红线,你的代码将无法通过编译器或解释器。JavaScript使用花括号,Boolean使用小写的true和false,//表示行注释。functiondoSomething(){a=true;if(a){...//Dosomething.}}Python使用缩进,布尔类型用首字母大写的True和False表示,#表示行注释。defdoSomething():a=Trueifa:...#Dosomething.Haskell有完全不同的语法:doSomething::IO()doSomething=doleta=Trueifathen...--Dosomething.elsereturn()2.语义所有编程语言具有大部分相同的特性:变量赋值、数字加法、字符串操作、调用函数等。但是,每种语言都有其特殊的思想,并以特定的方式行事。它们可以分为不同的模式(命令式、面向对象、函数式),但即使是相同模式的两种编程语言,在细节上也是完全不同的。当“声明一个类”、“调用一个函数”或“定义参数类型”时,您定义了程序的语义。有些语言遵循这样一套规则,而另一些语言则遵循其他规则。例如:在C++中声明的类可以扩展到多个类。当您使用“+”将数字和字符串相加时,您会根据语言的语义得到不同的结果。有些编程语言会因为类型不匹配而编译失败,但有些编程语言会自动将数字转换为十进制字符串。语法和语义的关系相当于用词(语法)来表达思想(语义)。您可以通过语言的句法表达语义。3.标准库***,每种语言都有自己的软件包,我们称之为“标准库”。在Python中,可以调用以下函数:print():在控制台输出信息len():返回数组的长度和各种有用的模块,如:json、threading等。在JavaScript中,可以使用console.log()取代了print()并且可以访问Object、Array和其他类。标准库是语言的重要组成部分。它可以给语言带来生命,没有标准库,你不能简单地做任何事情。具有讽刺意味的是,没有“标准的标准库”。每个标准库都与其他标准库有着根本的不同:??一些库只提供最少的方法集,而另一些则提供非常广泛的功能,因此开发人员基本上不需要依赖任何第三方库。基本思路上面我们介绍了一种语言的组成,然后我有一个基本思路:我们能不能找到一种方法把语法、语义和标准库清楚地分开?我们怎样才能实现这个想法?*第一步:只有程序员关心语法我要解决的第一个问题是语法。编译器和解释器有一种更有效的方式来表示代码,我们称之为抽象语法树。我们用代码描述的内容最终可以用下面的抽象语法树来表示:图:欧几里得算法抽象语法树如果仔细观察,你会发现上面的语法树可能来自多种语言。是蟒蛇吗?是JavaScript吗?还是C++?没关系:所有这些语言都有相同的语法树。当然,现实世界的例子要复杂得多。这就是我们用文本编写代码的原因:更紧凑、更易于编写和更易于阅读(有些人可能会有不同的看法)。我们从编程的第一天起就采用了这种方法,很少有人质疑它。举一个更现实的例子,抽象语法树将描述所选语言的语义(例如:类定义)。但是,语义相近的语言仍然可以共享同一个抽象语法树,可以进行一定程度的扩展。这非常有用,因为您可以自动转换部分代码。因此,我们可以将语法视为抽象语法树之上的人类思维。代码可能不会作为文本存储在任何地方,只能存储在文本编辑器中。如果您想在特定语言上使用不同的语法,那也完全可以。这不会影响其他人。实际上,我有点惊讶没有一个工具可以将代码从一种语言转换为另一种语言,而这是完全可行的。我想肯定有人尝试过,但放弃了,因为不转换整个标准库是不切实际的。显然,我也在尝试这样做。第二步。将标准库抽象为APIAPI是一个非常巧妙的概念。每个软件都可以通过API与其他软件进行通信。移动端应用可以通过API与服务器进行通信。服务器可以通过API与数据库通信。每个人都可以通过API与其他人交谈。这是一件很酷的事情。我为什么要在这里谈论API?因为这正是我们所需要的。API是语言的媒介。它们是一组语义,描述特定代码模块在外部提供的功能。无论是函数库、HTTP服务器还是其他东西。有多种方法可以声明API。可以是NPM上的JavaScript模块,在README文件中提供了API文档。它也可以是在代码中显式声明的API,例如TypeScript模块。也有可能没有API的声明,也没有明确的文档。但重要的是:API声明了代码模块的“外部接口”。你可以用其他语言重写模块内部的代码,但API不会改变。这就是API的美妙之处。编程语言很乱,但API很酷。前面我们提到了标准库,说过每种语言都有完全不同的标准库。如果我们能找到一种方法将标准库抽象成干净的API,那么我们就可以解决这个问题。尽管在语义上调用print("Hello")与在Java中调用System.out.println("Hello")不同,但它们实际上可以是相同的API。我们有两种方法来解决这个问题。要么我们告诉大家停止使用标准库并使用我们的“API层”。或者我们可以让计算机自动推断出你使用的代码。我不太喜欢“说服人们改变他们的方式”,所以我会采用后一种方法。我们不必为编程语言标准库中的每个函数都提供API。一般我们只能使用标准库中的几个函数。我们可能会自动将这些代码从一种语言转换为另一种语言。然后,我们只需要每个开发人员用这些API替换特定的标准库调用即可。别担心,计算机仍然需要你,至少现在是这样。第3步:让一切成为API现在我们有了干净的代码模块,定义了纯语义并将与标准库的交互抽象为API。下一步是什么?创建API。今天的代码库由多个文件组成,这些文件通过“导入语句”相互引用。这对我们来说很方便,但也意味着我们需要在脑海中勾勒出代码库的结构。任何一个地方的小改动都会在不经意间对其他地方造成毁灭性的影响,尤其是如果我们没有做好自动测试。而且,代码库会不断增长,编译时间也会逐渐增加。也许有更好的方法来解决这个问题。比如,模块化就是一个很好的方式。之前写过模块化(点此查看:https://medium.com/@fwouts/the-zenc-master-plan-c693bf3b265e),基本上就是:每一段独立的代码都应该抽象成一个API。我称之为模块。你不需要关心具体的模块是用什么语言编写的。在编写模块时,你不需要导入这些文件。事实上,此时该文件已不存在。您可以直接使用API,它们会自动加载这些功能。模块有什么好处?可以鼓励人们思考设计:首先你需要设计API可以减少认知开销:你只需要“填空”简化测试:你只需要测试API,你可以模拟所有依赖世界将变得更漂亮:没有语言障碍,没有庞大的代码库;更快乐的程序员,更快乐的客户第4步:玩得开心我不确定第3步之后会发生什么,但我认为每个人都会快乐。