胡谈编程语言:从C语言到Julia

犀见日月,天地方圆

有一天你会遇见一个彩虹般绚烂的人,从此以后,其他人不过匆匆浮云。

C语言

我想起人在童年蒙昧之时第一次在意识深处注意到并思考着太阳月亮时候的心情:它们是什么?
“太阳和月亮”,大人们有力的回答。
我想如果我活在一千年前,在我终于学会了太阳和月亮的概念之后,不用多久我就会知道另外四个字:天圆地方。
人之初见,几乎不能做什么有力的思考,只能被动的先接受一些东西,然后才能反过来怀疑这些基础是否完全合理。

C语言是伟大,几乎现代的IT业都构建于C语言之上—— OS,网络基础设施,都是如此。C如此重要,也许应该说C语言本身承担了某种重要的角色。当人类终于从机器语言变换到汇编语言之后,汇编仍然直接操控机器,最接近于本质才最强大,才能掌控一切。汇编是苦的,用起来一点儿也不甜,糖是必须的。所以将C语言看作是一门高级的汇编语言,继承了汇编对硬件的掌控能力,用起来还不苦了,似乎更符合其角色。毕竟C是天地初开那一划,给人世带来最新的认知:犀见日月,天地方圆。变量定义、类型系统、if、while、switch、return等语法结构如同阴阳五行一般成为构建、理解整个世界的基础。

OOP之C++ & Objective-c

两种最为有名的C语言在OOP思想下的变体。C既然承接于汇编,好的部分当然要继承,汇编不好的部分你敢丢弃么?C++承接C而继续向前发展,与C遇到了相同的问题:一部分的东西可以用OOP包装的更好更强大,但是那些不好处理的部分怎么办?一种方式是强行将所有东西统合在新框架中,激进派,结构完美主义;另一种方案是,one for the best。如果OOP的效力有限,那就让OOP把自己能做的事情最优雅的做到最好,其他的留给C语言本身就好了。是的,C++采取了前一种方案,将所有C语言所能干到的事情,对于程序的掌控能力都强行统合在一个框架中,所以你看到超级的复杂性,一些语法在局部的丑陋不堪。Objective-C所选择的道路我甚为赞善,明智的分工合作而不是想着自己全包干。

Java

Java就像个干什么事情都需要人服侍,打扮得冠冕堂皇的贵妇一般,容不得一丁点的不合礼法。诚然Java强大,横扫天下,能在诸多领域展现自己姿势和实力,但她的确太雍容了,以至于每个地方都要忍受她的至高无上的行事风格。
还记得吧,那些年我们是这样写Java的hello world的:

public static void main(string[] args)
{
     System.out.println("Hello World");
}

哦,别忘了,咱们得用类包装一下,所以得像这样:

Class Main
{
  public static void main(string[] args)
    {
         System.out.println("Hello World");
    }
}

贵族总有那么多奢侈的礼法,你要是愿意时时刻刻都这样伺候Java,嘿,小伙,祝你前途坦荡,平步青云,DOG RICH,NO FORGET.

JavaScript

毋庸置疑JS已近统治了前端,V8和Node.js的发力将JS的影响力以一种开天辟地的方式带入到后端世界。CoffeeScript等JavaScript的包装语言也不断站在巨人的肩膀上,攻城略地。更重要的是仔细看看chrome的威力吧。在C/S模式中,web化大势所趋。浏览器将成为除开OS之外最重要的软件。服务将基于HTML5等新标准全面web化。so,这跟JS有几毛钱关系。HTML5 + CSS3进行页面表现的控制,那么当要使用浏览器在本地对事件进行一些处理的时候怎么调用浏览器?和现在一样,浏览器支持某种前端语言,提供API,如同OS提供系统服务一般将broswer自身的服务开放出去。JS是首选,不仅仅是它现在统治了前端,更是因为对于JS优化的努力已近很明显的促成了JS成为一个中间平台,可以让CoffeeScript等语言一面兼顾对程序员的友好性,另一方面不必费尽心思,从头开始进行优化,更重要的是JS原来那些库、框架、有用的Code仍然可以无缝集成!是了,JS越来越成为一个中间平台,一个连接web底层服务和上层应用代码的虚拟机。用C我们搞出unix、linux这样的平台来运行各种语言编写的程序,JS也能在web上架构起V8这样的系统级开发平台。OS于V8的共同之处在于对于更上层的application来说,它们都只是容器而已。

Opa

Opa是什么?
问问自己如果从前端到后端要掌握多少东西吧!web开发始终有一个问题是前端和后端的开发语言不是一样的。这真是要了程序员的命,特别是国内的程序员,可知老板有多希望你是一个全栈式的Coder啊。前后端一统的开发模式是一种难以避免的需求。是JS,还是JS。目前也只有JS同时在前端和后端都混得风生水起。但道路既然已近指明,竞争还不会出现么?感谢上帝。It’s Opa.
Opa对比JS来说,Opa有强大得后发优势,并且是经过专业团队,专项研究,专门针对WEB编程而设计的杰作。后发优势使得Opa一方面吸取Web开发各家之长,并将一些随着演进才出现的问题(这些问题在JS/PHP等语言诞生都还不明显,或者设计时没有足够好的解决方案,已近让JS/PHP开发人员受尽折磨)内建在语言中给出优雅的解决方案。或对于同样的问题给出前代语言更为高效、更为现代化、更具程序员友好性的解决方案。使用Opa语法比JS更简洁,不让CoffeeScript;从此前后端一统,更重要的是Opa生在云时代,对于云的衔接是JS、PHP这些前代语言完全无法匹敌的一个所在。
每一个现代的WEB开发人员,都将不可避免的接触两种数据格式:JSON和XML。JSON是JS内嵌的数据结构,可以直接转化为Obj进行操作。XML呢?这么多年了,有什么语言把对XML的支持内嵌到语言中去了。我已近写烦了C/C++的XML读写和解析了。大量重复的代码,大量无聊的工作仅仅实现了一个XML文件到一个内存对象的转换。阿门,无知是罪,浪费更是罪。Opa是专为Web编程、并且专注于Web编程的语言,内建XML支持,可以直接将XML定义为Opa的工作对象。这意味着我们可以保持XML文件良好的阅读性的同时,还能够直接将一个XML文件反序列化成为一个Opa的XML对象,终于摆脱了该死的XML解析之罪。

Haskell

神人造出的东西总是美得让人难以置信。
欧拉恒等式
Einstain 质能方程
所以编程界呢?
It’s Haskell.
一大群PhD搞出的东西,能怎样形容一下呢,优雅,优雅,还是优雅!Haskell基于数学,掌握它之后你可以把你的代码写的像英文一样简单易懂。易懂的不仅仅是别人阅读你的代码时易懂,而是程序员本身就可以按照数学的逻辑和语言表达的自然顺序快速的写出程序来。你可以想象自己是在做数学证明题,而最后惊奇的发现你已近写好了解决实际问题的代码。惰性计算和函数不变态将使你免于命令式编程的诸多灾难。
那么问题是为什么Haskell不流行?
借用流行的说法是:有些语言流行仅仅是因为它们流行而已。意即它们之所以流行是因为它们是流行的。这是一个递归。
所以现实的情况是,haskell的确优雅美丽,强大有效,但就是不流行。故而像要使用Haskell混饭吃是一件十分困难的事。至少国内困难的基本无法找到有规模性质的招聘信息。但学习Haskell是值得的,就像学习数学和物理是值得的道理是一样的。
终于摆脱C系语言无聊的括号,我欣然接受函数组合式牛仔新技能。
我们真的需要那么复杂的语言么?Null是个鬼!
OOP不是只有OOP才是一种实现。Haskell将带你领略出于数学方法的精妙解答。

Pyhton

脚本、动态、函数式。Python是令人着迷的。哲学比任何其他东西都更能说明一切。C++/Java很有科学的道理,但是哲学呢?
Python是一门以哲学为指导的语言。有好的哲学才有好的文化,有好的文化才有好的社区。对于开发者来说,选择一个语言就像选择一个国家的国籍,你不仅仅购买语法和语义,你也购买了经济和文化,以及你怎样获得生计和力量的规则,就像他们常说的:为了避免一个“死”语言控制了世界,购买需要谨慎。【引用网文,作者不详】相比Haskell来说,Python提供了一个优雅而现实的解决方案,甚至在google中也能并肩成为其第二大开发语言(至少在前几年是这样的)。虽然Python的执行速度较慢,但这和Objective-c殊途同归,自己搞不定的交给别人,信任别人就好了。性能么?哥们调用C就OK了。

Julia:Walk as Python,Run as C

Julia的目标在于让高性能的科学计算人人可用。是的,这看起来并不是为通用编程领域设计的语言。But,事实也是这样吗?
Walk as Python,不仅仅形态和语法与Pyhton相似,而且比Python更优雅,另一个好消息是Julia和Python是可以无缝对接的。你可以在任何你想的地方使用Python(当然如果Julia更好的时候我不建议你这样做,我相信Python也不建议这么做,因为这有悖于Python的哲学:There should be one– and preferably only one –obvious way to do it.),不过那么多Python库我们怎么能放过呢?尽情拿过来使用吧。
Run as C 美丽的Julia克服了Python的致命弱点!美貌才是这个世界上最难打理的奢侈品。美丽不容易,但内心的涵养更是难得。有一天你会遇见一个彩虹般绚烂的人,从此以后,其他人不过匆匆浮云。
终于开到有一门语言的下标不是从0开始的了!感谢上帝。让我们回归真实的世界,自然逻辑的法则啊,不该为了强行将0加入其框架而折磨世人。
Julia是我们同时代的美人,她还很年轻,诞生于2012年。

Go

Go语言从Haskell和Python那里学到了不少,但还不够好。文艺要传达众人必先得其美。咱们看看Go的变量声明如何?

var v1 int = 10 // 正确的使用方式1
var v2 = 10 // 正确的使用方式2,编译器可以自动推导出v2的类型
v3 := 10 // 正确的使用方式3,编译器可以自动推导出v3的类型

所以,当我们需要变量的类型的时候我们就只能在其后面突兀的贴入一个int/double/string的标签?

func readValues(infile string)(values []int, err error)

这放在函数返回值的时候尤为难看,是真的一种难看。Programming发展的方向是不断靠近自然语言,但自然语言有太多的信息冗余,完全的自然并不适合作为编程语言的最终形态。一种很明显的区别用来说的语言和用来写的语言是不尽相同的,它们之间具有其自身良好的区分度,以备在需要的时候能将两者甄别。语言在有些时候是不必那么完整的,定义一个int型变量 varx,我们可以这样说 varx is value of int,变量名在前,变量类型到了最后(Go的做法);另一种同样达意的说法是 we define a int value varx.我更倾向于我们使用varx的时候我们需要在心里默念 varx is value of int,但在第一次正式而完整的定义varx的时候,你难道不是这样告诉你自己的:定义一个int型变量varx(define a int varx),后面需要用到它。所以我以为这不是文艺的复兴,而是某种倒退了。也许10年20年之后我将承认我今天的无知。然而我的辩解是:一个人一个事物表现其特立独行太过超前拔世,就总会受到某种警告。一旦有些特性超越了世浪太多,我不得不在当下给它贴上一个反人类设计的标签。

C#

我读书少,不知道有没有合适的寓言或者童话故事来贴合一下C#。C#强大和实用性已近经过了验证。问题是对于C++这样复杂语言人类都能以之构造精美绝伦的程序,这给我的想法是不论对于多复杂、多么庞大、多么难以掌控的工具,人类只要投入进去就能够取得自己想要的成就,而不是反过来证明了C++是多么不可或缺。C#的特性太多太多了,每一个版本的更新你几乎都能看见更新。当然更新是必须,更不能成为非难的借口。判别的标准在于:频繁的更新是否将其核心打造的越来越完美无缺,是否在完善其核心功能基础之上添加了正真有效、有趣的东西;而不是在合适和妆著之上添上了不予自己搭配的其他东西。一套价值10W的衣服配上一个几十块地摊货的包包是怎样的一种感受?
而另一个问题是我们真的需要如此复杂的工具来解决问题吗?这一点Go是有哲学的,这是Go带来的最大的进步:化繁为简,少即是多。有什么事情可以用C++干到而C干不到?当然得承认有些地方C太低级了,实现起来超级麻烦。不过如果只是解决问题,你需要使用C++这种核武器级别的复杂工具么?低速状态下使用牛顿力学就好,不要动不动就拿着相对论的武器进行轰炸。避免大量无谓的计算,世界才能和平。

整体来看,编程语言正在不断从主流的C系语言已有的桎梏中解放出来,不断学习动态语言、函数式编程和其他小众编程界涌现出来的优秀特性。从语言发展图谱来看,语言的确在向着动态和函数式两个方向迁移。貌似新的语言不说自己支持点函数式编程特性都不好意思是自己新出生的语言了。据说最近微软的F#语言莫名的火了起来,从F#的定位来看,C#的界面上的优势F#将在.NET平台同享,而F#最大的优势是它比C#朴素了很多,不再添加很多花里胡哨的东西,更是大规模支持了函数式编程,微软的改变颇为耐人寻味。

编程语言影响力图谱

这里写图片描述

这里写图片描述

可以看到,在整个编程语言影响力图谱上,最大最明显的两个节点其中一个是C,另一个是LISP/Haskell.

关于C语言不足之处的一些思考

C的不足之处不仅仅在于使用指针时类型和名字不分,更多的时候是关键字上设计的失误,比如static关键字在文本全局使用时表示变量或函数的可见性,在函数中却用来实现局部变量的静态存储,这严重违反了unix“do one thing at a time and do well”的设计哲学,还有空指针这种东西,没有最好,如果有也不应该使用NULL这种常量式的定义,容易和0本身混淆,void指针任意转换的设计更是糟透了,这再一次违反了unix的设计哲学,另外不得不说的是常量定义即可以用#define也可以用const,却还是推荐使用#define来进行定义,然而个人觉得这的确是语言设计上的某种失误,即最开始时没有好好考虑谁来承担定义常量的责任,纵观C语言整个语言特征体系,的确是严重违反了单一职责的设计原则,并且在那个缺乏语言设计实践经验的设计结果就是关键字责任的混乱不堪,语义限定的要么不完整要么有些臃肿,以现在的视角来看,C语言真是一门缺乏精心设计的语言,很多缺陷都可以明显的避免。诸如访问权限,模块化等功能使用namespace、private、public、protected等关键字完全可以实现static、external等关键字所想要实现的语言特性,另外一点可能是最致命的一点是C的语言逻辑也可能存在走了弯路的设计,这导致了模块化成本的提升。
在声明指针时常量指针和指向常量的指针的区别简直恶心,而这完全可以避免:

ptr<const int> p; //指向常量的指针,指针值可变,指针所指向的变量本身不可被改变

const ptr<int> p; //常量指针,指针值本身不可变,指针所指向的变量本身可以被改变

又如C没有new这样的关键字操作符来明确区分堆内存分配和栈内存分配,以至于函数内部声明的指针也不能返回,严重加重了程序员的内存管理负担。然而,我们的确需要一个new/delete操作符来明确承担的堆内存管理职责,而不是与静态存储区混用。
…….

总而言之,C语言是一门可以设计得更加优美简洁的语言。

那么,如果C语言本身可以在不减少其功能的前提下重构为一门更加精巧,简洁、已用的语言的话,我们就要问问实现系统级的编程我们到底需要多少的语言特性呢?

结合使用GCC的扩展来实现Linux的事实,我们几乎可以肯定实现系统级的编程以C语言核心特性来说已近足够,而C语言本身还有精简和优化的空间。所以实现系统级编程并不在本质上要求语言本身被加入了许多的特性,满足开发需求的核心特性足以让一门语言十分精简而保持强大的开发功能,如scheme,如Lua。C语言的复杂度还可以降低而同时保持其已有的开发能力。

设计一门语言,以最为精巧、简约的语言架构满足其强大的开发需求,去掉C一些缺陷性的特性,加入一些更加友好的现代特性,但是
第一:语言的特性应该尽量的少;
第二:语言的特性应该职责明确,呈现正交分布形态;
第三:不要强求多范式,从C的经验来看,仅仅是过程式开发就已近具有强大得开发潜力了,虽然有时候缺乏某个特性的开发会显得十分繁琐和复杂,但在保持语言本身精巧、简洁、易用的设计目标下是有一些必要的牺牲,这个方面需要做出明智的权衡;
第四:语言本身的特性和配套的基本库要具有正交性,这样才能让两者相互配合,发挥出最大的威力;
第五:借鉴、吸收可以,但请丢掉继承C/C++遗产的想法,丢掉历史的包袱毫无羁绊的进行自己的设计才是C最伟大之处。

一些思考与笔记

C++就程序语言设计方面来说即不优雅简洁,又不安全健康,除了傲视群雄的性能似乎也没有什么特别值得称道的实际之处,总体看来还是一个失败的语言设计。

C/C++是性能工具而不是开发效率工具,而Java是一种很好的效率工具,虽然还不那么很好。

选用C/C++进行开发的代码如果肯下功夫依然可以健壮的运行,但就像你现在还活在这个世界上一样,不能与时俱进的你,还能对这个世界有几分影响。

一些在其他语言中不存在的问题却成为了C++程序员必须小心应对的缺陷,需要学习各种具体操作条款、编程约定和专门知识以避免陷进,提升开发效率,这简直无聊透顶,并且C++居然没有统一的实现,语言自身也没有版本号(标准文档的版本号和现实还有着实现程度的鸿沟),完全不像JAVA、Python等现代语言一样有专门的组织机构发布最新的语言版本和标准库,而C++的标准委员会只是制作要收费的标准文档而已,但他们并不自己完成开发!!并且C++的标准库实际上并不那么简单易用,强制让所有数据结构靠向迭代器算法的结果就是在使用时总是有些特殊处理和注意事项,这样搞来搞去真的有意思么?标准库的失败对开发人员来说就是一个致命伤。另外C++语言的整体结构都显得有些混乱不堪。哪些事情应该交给编译器做,哪些事情需要程序员自己操心完全没能进行良好的区分。本来应该由编译器隐藏的东西却偏偏只做一半,还剩一部分又交回给程序员是什么意思?到头来程序员不仅需要了解那些应该被编译器隐藏的东西,反而又需要深入了解编译器内部的实现逻辑了!难道人就是这么喜欢给自己找事儿么?总之,C++毕竟是中古时代遗留下来的语言,其整体设计和运作方式完全保持了自己老旧的学院式做派,在现代编程语言界简直是个个性十足的奇葩。

编译器与程序员 Compiler & Programmer
程序员不了解他的编译器简直就是灾难!在整个程序开发过程中程序员和编译器之间的关系十分微妙,应该得到十二分的重视,然而我们的教育却并未这样做,这真是无可奈何的悲哀!
在程序开发过程中程序员和编译器各承担什么责任,谁做了什么事情,谁在什么时候会做什么事情,谁在什么时候该做什么事情都必须明确。这需要程序员十分了解自己所用的编译器,不然程序员所谓的开发实际上就是盲写,是一种误打误撞,这种态度应该被专业程序员所抛弃!

我们需要一门怎样的编程语言?
这门语言要有C一样简单与性能,具备C++和Java强大的抽象和建模能力,还要像Haskell和Python一样优雅整洁,支持多种编程范式,能同时满足系统级、平台级和应用级编程需要,能适应大型工业级软件开发的严苛挑战,具有通用性,还要拥有足够多的优秀且丰富的库和框架,以及一整条完整好用的配套开发工具链。

通用程序设计语言如C系语言采用了自底向上的进化模式,不断从机器层面抽象出更自然的语言系统,而LISP系语言似乎是以自顶向下的延展方式发展着,以不断从数学似的语言中泛化为更加自然的语言系统。C和LISP一者面向机器底层,一直面向通用图灵机模型,是一种两极化的存在关系,但总体趋势都是在向着自然语言系统方向发展,两者必将有所交汇而产生一种强大而至美的通用编程语言,那么会是什么呢?是Haskell么?是Julia么?

最后的选择

在系统级和大型高性能程序的开发上我们已近有了C和C++,但在开发语言的进化图谱上我们需要更进一步了。这已近迫在眉睫。C++为了兼容C而背负和牺牲了太多太多,而Java因先天对多编程范式支持不足已显后劲不足。我们不能要求未来的年轻人也必须背着这些包袱才能继续在软件界前行。这些已近狠狠折磨一代人了。新的时代需要新的语言,是时候做出选择和改变了。如果你活在这个时代,那请关注Clojure、Rust、Go、Python、Haskell、Julia吧。如果你生活在下一个编程时代,不要怀疑,请把这些语言换成你们时代新出现的语言,未来应该掌握在你们自己手中。
Life is short, u must find what u love.

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值