阅读更多
毫无疑问,不同的编程语言间存在着很多差异性。那么对于这种差异性开发者应如何解决?本文就来一探究竟。

以下为译文:

我一直在告诉别人:“编程非常了不起。”在你有任何想法的时候,都可以编写软件,然后愿望就实现了。这很真实。与建立物理的东西不同,首先你需要建立整个工厂,而软件的扩张相对非常容易。你可以找到所有已经编译好的组件,而且是免费的,拿来就可以用。建立好一段代码后,就可以重复使用无数次,而无需花钱。听起来很厉害的样子。

但有时候不是这样的。编程带给人的惊喜只是暂时的。在建立了很多代码以后,在写代码的过程中你会不断遇到让人迷惑的错误。一旦你习惯了特定语言和框架的模式后,一旦你需要第二种天性去掌握所选语言中非自然的语法时,编程的伟大之处就不复存在了。

更别提我们有无数种不同的编程语言。每当开发人员面对特殊语言的语法而深感沮丧时,他们都会想“为什么我们不能创建一种新的语言改正这个问题呢?”有些人还真的这么做了,很幸运的是自然选择已经淘汰了很多很差的语言(有时也有意外,比如至今PHP还存在)。一旦一门新的语言开始在一群开发者中流行起来,那么恭喜你 ,现在又出现了一个新的开发者社区,他们互相合作,努力让这门特殊的语言发展壮大。

每一种新语言的诞生所带来的创新,都能造福我们每一个人。但是有时也有不利的一面。有些人可能写了一些非常有用的开源JavaScript库,但是从事Python的开发者却完全没法用。他们不得不自己写一个Python版本的函数库,或者用JavaScript重写所有代码。再想想当前有多少种语言和框架。如果你不觉得这很荒谬的话,那只能说明或许你在软件开发这一行太长时间,已经习以为常了。

语言都包含些什么?

各种编程语言都在以下三个方面上有着很大的不同:语法、语义和标准库。

没错,我知道,我过于简化它们了,但是听我给你解释。

1. 语法

如果不遵循语法,那么你会在编辑器中看到各种弯弯曲曲的红线,而且你的代码也无法通过编译器或解释器。

JavaScript使用大括号,布尔型使用小写的true和false,用//表示行注释。
function doSomething() { a = true; if (a) { ... // Do something. } }
Python用缩进,布尔型用首字母大写的True和False表示,用#表示行注释。
def doSomething(): a = True if a: ... # Do something.
Haskell又有完全不同的语法:
doSomething :: IO () doSomething = do let a = True if a then ... -- Do something. else return ()
2.语义

所有编程语言都有大多数相同的特征:变量赋值、数字相加、字符串操作、调用函数、等等。

然而,每种语言都有特殊的思想,以特定的方式运行。可以将它们划分成不同的模式(命令式、面向对象、函数式),但是即便是两个相同模式的编程语言在细节上也是完全不同的。

在“声明类”,“调用函数”,或“定义参数的类型”时,你定义了程序的语义。有些语言遵循这样一套规则,而其他的遵循别的规则。比如:C++中声明的类可以延伸到多个类。当你使用“+”将数字和字符串加到一起的时候,根据语言的语义会得出不同的结果。一些编程语言会因为类型不匹配而导致编译失败,但是有些编程语言会自动将数字转换成十进制的字符串。

语法与语义的关系就相当于用单词(语法)来表达想法(语义)。你可以通过语言的语法来表达语义。

3.标准库

最后,每种语言都有各自的软件包,我们称之为“标准库”。

在Python中,你可以调用如下函数:
  • print():在控制台输出信息
  • len():返回数组的长度
  • 以及各种实用的模块,例如:json,threading,等等
在JavaScript中,你可以使用console.log()代替print(),可以访问Object、Array等类。

标准库是一门语言中重要的组成部分。它可以为语言带来活力,没有标准库,你无法简单地做出任何东西。

很讽刺的是,并没有“标准的标准库”。每个标准库基本上都不同于其他库:一些库只提供最低限度的方法,而有些库则提供非常广泛的函数,所以开发人员基本上不需要依赖任何第三方库。

基本的想法

以上我们介绍了一门语言的构成,接下来我有一个基本的想法:我们是否可以找到一种方法清晰地分割语法、语义和标准库呢?我们又如何实现这一想法呢?

第一步:只有程序员关心语法

我想解决的第一个问题就是语法。编译器和解释器拥有更加有效的方式表现代码,我们称之为抽象语法树。我们用代码描述的内容最终可以用如下抽象语法树表示:

图:欧几里得算法的抽象语法树

如果仔细观察,你会发现上述语法树可能来自多个语言。是Python?是JavaScript?还是C++?这都无所谓:所有这些语言都拥有同一个语法树。

当然,现实的例子会更加复杂。这就是为什么我们用文本写代码的原因:更加紧凑,更加易于书写,还有更加易于阅读(有人可能有不同的看法)。从编程诞生的第一天,我们采用的就是这种方法,很少有人对此质疑。

对于一个更加现实的例子来说,抽象语法树会描述所选语言的语义(例如:类的定义)。但是拥有类似语义的语言之间还是可以共享同一个抽象语法树,并可以扩展到一定范围。这非常实用,因为你可以自动转化部分代码。

所以,我们可以把语法想象成抽象语法树之上的人类思维。代码可能并不会以文本的形式存储在任何地方,仅在文本编辑器内。如果你想在特殊的语言上使用不同的语法,也完全可以。这不会影响到别人。

我其实有点惊讶怎么没有一种工具可以将代码从一种语言转换成另一种语言,这完全可行啊。我猜肯定有人试过,但是放弃了,因为如果不将整个标准库转换过去的话是没有实用性的。很明显,我也在做这方面的尝试。

第二步. 将标准库抽象成API

API是一个非常高明的概念。每个软件都可以通过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替换具体的标准库的调用。不用担心,计算机依然需要你,至少现在需要。

第三步:把所有东西都做成API

现在我们有了干净的代码模块定义的纯粹的语义,并将与标准库的交互抽象成了API。

下一步做什么?创建API。

现今的代码库有多个文件构成,彼此之间通过“import语句”互相引用。这对于我们来说很便利,但是这也意味着我们需要在脑海中勾画代码库的结构。任何一个地方发生小的变化,都可能在不经意期间给别的地方带来破坏性的影响,尤其是如果我们没有做好自动测试的话。而且,代码库会不断增长,而编译的时间会逐渐加长。

也许有更好的方法解决这个问题。比如模块化就是个好办法。

我之前写过关于模块化的文章(点击这里查看:https://medium.com/@fwouts/the-zenc-master-plan-c693bf3b265e),基本上来说:每段独立的代码都应该抽象成API。我称之为模块。你无需在意一个具体的模块使用什么语言编写的。在写模块的时候,你不用导入这些文件。实际上,这时文件已不复存在。你可以直接使用API,它们会自动加载这些功能。

模块有什么好处?
  • 可以鼓励大家考虑设计:首先你需要设计API
  • 可以降低认知的开销:你仅需要“填空”
  • 简化测试:你只需测试API,并可以模拟所有的依赖性
  • 世界会变得更加美好:没有了语言之间的壁垒,没有了巨大的代码库;程序员更加快乐,客户更加快乐
第四步:尽情享受

我不确定第三步之后会发生什么,但是我觉得所有人都会很满意。
  • 大小: 341.7 KB
  • 大小: 91.3 KB
来自: CSDN资讯
3
0
评论 共 1 条 请登录后发表评论
1 楼 aa87963014 2018-07-24 09:42
非常赞同,现在的语言太多了语法又差异太大增加无谓的学习成本很恶心

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 怎样解决编程语言之间差异性问题?(转载)
  • 浅谈编程语言之间的区别 1、shell程序 windows的shell叫做cmd,它会运行.bat的batch文件。Linux中的shell程序被称为bash或者sh。shell程序的问题在于程序超过百行之后扩展性差,并且比其他语言的运行速度慢很多。 2、C和C++语言 极其重视性能的时候使用,它们有许多细节需要自己处理,处理不当就会导致程序崩溃和其他难解决的问题。而C++和C看起来很像,但是特性完全不同。 ...
  • Stata - 内生性问题:处理方法与进展 ……Stata 连享会精彩推文…… 【在线观看】连玉君 - 内生性问题:处理方法与进展 相关链接 IV 估计 DID-倍分法 ……Stata 连享会精彩推文…… 关于我们 【Stata 连享会(公众号:StataChina)】由中山大学连玉君老师团队创办,旨在定期与大家分享 Stata 应用的各种经验和技巧。 公众号推文同步发布于 【简书-Stata连享会】 和 【知乎-连玉...
  • 各类编程语言对比 C 诞生在计算机系统结构时代,是用于写操作系统的语言 重点:指针、内存、数据类型 语言本质:理解计算机系统结构,使得编写的程序效率更高(内存更小) 解决问题:性能 适用对象:计算机类专业,底层程序的开放 Java 诞生在网络和视窗时代 面向对象,进一步抽象,使得代码复用更灵活 用跨平台方法解决跨平台问题 重点: 对象、跨平台、运行时 语言本质:理解主客体关系 解决问题:跨平...
  • 几个JavaScript的浏览器差异处理问题 原文链接:http://www.nowamagic.net/librarys/veda/detail/1507 JQuery确实是个很好用的库,你可以不用考虑很多细节方面的事情。但很作为一个web前端,处理和了解浏览器差异一个重要问题。下面将介绍一些总结,先介绍没有使用js库的情况。 1. setAttribute方法设置元素类名 在jQuery中,直接使用attr(
  • 多重继承引发的二义性问题解决方法分析
  • 如何解决不同浏览器之间的兼容性问题 常见的浏览器兼容性问题解决方案大致有以下九种形式:    一、不同浏览器的标签默认的外边界和内填充不同   问题表现:不加样式控制下,margin和padding差异较大   解决方案:css里 *{margin:0; padding:0;}   备注:这是最常见也是最易解决的一个兼容问题,几乎所有的css文件开头都会用通配符*来设置各个标签外边界和内填充为0
  • 浅谈各类编程语言之间差异 引 浏览各大编程相关的网站, 总是能看到有关于编程语言的争论, 这些争论使得想要学习编程的人变得疑惑。 总会让人陷入到底什么是最好的编程语言, 我该学什么, 这样的疑问中。 我曾经也陷入过这样的疑惑中, 入行做“码农”大概也有一年半的时间了, 借着2018的过去, 2019的开始, 尝试总结一下这类问题, 给过去的疑问一个交代, 给新人一份细微帮助(但愿)。 机器码编程(汇编语言) 汇编语言...
  • 各类编程语言区别
  • 特征共线性问题分析 1.概念: 多重共线性是指自变量之间存在一定程度的线性相关,会给变量对模型的贡献性带来影响。即若有两个变量存在共线性,在相互作用计算后,其一的变量的影响会相对减弱,而另一个变量的作用却会相对增强。 2.产生原因: (1)没有足够多的样本数据 (2)选取的样本之间本身就客观存在共线性关系 (3)其他因素导致:数据采集所采用的方法,模型的设定,一个过度决定的模型 多数研究者认为特征共线性本
  • 多处理机Cache一致性问题解决办法 1. 造成Cache一致性问题的原因出现不一致的原因有三个:共享可写的数据、进程迁移和I/O传输。2. 解决办法解决多处理机Cache一致性问题提出了两种解决办法:侦听一致性协议和基于目录的一致性协议。由于多数SMP(对称多处理机)结构是采用总线互连的,侦听一致性协议是基于侦听总线事务来保持Cache一致性的协议,所以多数产品采用侦听协议。基于总线互连的SMP是通过高速共享总线将若干个商用的微处理器
  • 不同浏览器之间的一些差异整理
  • C++虚基类解决二义性问题及执行结果分析 由于C++中允许多继承,所以会出现二义性问题:在多个派生类中,定义了相同名字的方法,这时再在main函数里面通过基类调用该方法时,编译器就犯难了。因为它不知道你到底是想用哪一个派生类里面的方法。 那么,现在又有了一个问题:假如有两个派生类DerivedA和DerivedB,它们的同名方法一个有参数,一个没有参数,是不是不会出现二义性问题了? 或者说,这两个派生类方法的一个是privat
  • 浏览器之间样式差异———解决 做前端开发,调试是必不可免的。鉴于谷歌强大的调试工具,一般开发还是用谷歌浏览器做调试比较好。 但谷歌有利也有弊,因为谷歌有自动补全机制,所以有些错误我们还是要借助其他浏览器来进行调试。 浏览器之间内核不一样,的确会存在差异,如果真的是内核之间大的差异引起的,那就没办法了。但是也有可能是默认样式引起的,因为浏览器之间的默认样式也不一样。一般都会引入重置样式尽量消除浏览器之间差异。可以引入norm
  • 9.并发编程的三个概念(原子性、可见性和有序性)存在的问题及其解决方案
  • 分布式系统Session一致性问题 转载地址:https://www.cnblogs.com/study-everyday/p/7853145.html session的概念 什么是session? 服务器为每个用户创建一个会话,存储用户的相关信息,以便多次请求能够定位到同一个上下文。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中
  • 各种编程语言这间的关系图
  • C++中常见的两种二义性问题及其解决方式 --------------------------------一、“倒三角”二义性问题------------------------------- 问题描述:卤煮之所以称之为“倒三角问题”,是因为这一类二义性问题所处的继承体系类似于倒三角形状,如图: 这样,在子类中就存在父类A、B的两份show(),在调用的时候就会出现二义性问题,这种问题该怎么解决呢? 面对问题: //下面这种情
  • 变量之间差异是显著的.
  • 多重共线性问题的几种解决方法 在多元线性回归模型经典假设中,其重要假定之一是回归模型的解释变量之间不存在线性关系,也就是说,解释变量X1,X2,……,Xk中的任何一个都不能是其他解释变量的线性组合。如果违背这一假定,即线性回归模型中某一个解释变量与其他解释变量间存在线性关系,就称线性回归模型中存在多重共线性。多重共线性违背了解释变量间不相关的古典假设,将给普通最小二乘法带来严重后果。
Global site tag (gtag.js) - Google Analytics