[后篇]最好的编程语言(如何不再担忧,爱上代码)

原文:The Best Programming Language (or How to Stop Worrying and Love the Code) by A. Castro-Castilla

点击看前篇

Java

    和C#一样,但有JVM。它面世最早(实际上C#模仿了它),算是面向对象语言界的“标准”。从网络应用到 游戏,它无处不在,只缺席嵌入式设备和高性能并行计算软件。它(尤其是它的虚拟机)为许多其他语言提供了基础。 Processing可以作为一个有趣的例子,它是一个皮囊语言(只是披上马甲的Java),被应用于教育和数码艺术。我什么时候推荐用Java:
  • 多数情况:如果你希望获取大量人力和知识储备,即,你想要别人维护你的软件。
  • 如果你需要通用于尽可能多的设备的多平台虚拟机。
Java7的读取文件的代码例子:
import java.util.List;
import java.nio.charset.Charset;
import java.nio.file.*;

public class ReadAll {
    public static List<String> readAllLines(String filesname){
        Path file = Paths.get(filename);
        return Files.readAllLines(file, Charset.defaultCharset());
    }

   public static byte[] readAllBytes(String filename){
       Path file = Paths.get(filename);
       return Files.readAllBytes(file);
   }
}

你大概已经见过很多Java代码,所以我就用类定义来烦你了。

Javascript

    2010年代的通用语,网络的语言。有趣的是,它以前被认为缺点多多、十分局限,但现在大量的程序员已经证明,只要遵循规范,使用技巧,Javascript也可以很优秀。尤其是它的大量的库和实现,弥补了Javascript的设计缺陷和功能缺失(比如模块系统)。拜它们所赐,现在甚至有了针对服务器的Javascript,它美妙的对称性终于穿过前端,来到了后端。
    人们投入大量精力研究如何改善Javascript性能及其它可以编译为Javascript的衍生语言。这证明了用户群是一种语言所能拥有的最强大的资本之一(甚至可以说是唯一)。有趣的是,无数的库反复在做同样的事情,使得库开发者在这一领域的竞争空前激烈。看Grunt和Gulp的例子,或者一大波互相竞争的Javascript衍生物(Coffeescript,Typescript,Livescript等等)。太疯狂了。
下面的代码展示了Javascript基于原型的类和继承:

function Car(brand, weight) {
  this.brand = brand;
  this.weight = weight || 1000;
}
Car.prototype.getPrice = function() {
  return this.price;
}

function Truck(brand, size) {
  this.constructor(brand, 2000);
  this.size = size;
}
Truck.prototype = new Car;

var cars = [
  new Car("Mazda"),
  new Truck("Volvo", 2)
];

for (var i=0; i<cars.length; i++) {
    console.log(cars[i]);
    console.log("brand: "+cars[i].brand+". weight: "+cars[i].weight+"." + (( cars[i].hasOwnProperty('size') ) ? " size: "+cars[i].size : ""));
    console.log("Car: %s. Truck: %s\n", cars[i] instanceof Car, cars[i] instanceof Truck);
}

使用Lo-dash库的类似函数式的代码:

var characters = [
  { 'name': 'barney',  'age': 36 },
  { 'name': 'fred',    'age': 40 },
  { 'name': 'pebbles', 'age': 1 }
];

var youngest = _.chain(characters)
    .sortBy('age')
    .map(function(chr) { return chr.name + ' is ' + chr.age; })
    .first()
    .value();

我觉得把两种风格混合起来很酷,只要你掌握了Javascript的特性(是的,比如this的用法)。

OCaml

它有点像Haskell,但更能满足程序员的想法。在必要的时候,为了更容易的解决方案牺牲了一些语言的纯洁性,比如过程式或者面向对象的方法最为有效的情况。 有些公司使用OCaml,我想就是为了它相较于Haskell的这个优点。看看下面的片段:
let n_arrays_iter ~f = function
  | [] -> ()
  | x::xs as al ->
      let len = Array.length x in
      let b = List.for_all (fun a -> Array.length a = len) xs in
      if not b then invalid_arg "n_arrays_iter: arrays of different length";
      for i = 0 to pred len do
        let ai = List.map (fun a -> a.(i)) al in
        f ai
      done
看起来很像Haskell,对不对?但那个for循环有如此有命令式特色……

PHP

    不要先入为主地认为PHP很可怕。向斯巴达人学习,享受PHP的折磨吧。有个好消息:如果你享受用PHP编程,那你就是真正的程序员了。这也是自由职业者常用的语言。什么情况下用PHP?
  • 如果你想要世界上最大的网络程序员资源库。
  • 如此而已,没有别的理由了。
漂亮的PHP代码,希望你喜欢美元。

function hashJoin($table1, $index1, $table2, $index2) {
    foreach ($table1 as $s)
        $h[$s[$index1]][] = $s;
    foreach ($table2 as $r)
      foreach ($h[$r[$index2]] as $s)
        $result[] = array($s, $r);
    return $result;
}

$table1 = array(array(27, "Jonah"),
           array(18, "Popeye"),
           array(28, "Alan"));
$table2 = array(array("Jonah", "Whales"),
           array("Jonah", "Spiders"),
           array("Alan", "Ghosts"),
           array("Bob", "foo"));

foreach (hashJoin($table1, 1, $table2, 0) as $row)
    print_r($row);


Python

    这是种美观的语言。我喜欢它的基于空格的块结构,没必要老是用难看的分号。我如此喜欢它,以至于打算这样写Javascript。但这事取决于口味,实际上很多人正好因此不喜欢这种语言。这是种简洁的语言,能减轻用户语法上的负担。尽管其效果有争议,这种语言依然有庞大的拥护者群,和它的同伴Ruby相比,优势明显。这两种语言之间很难抉择,不过Python似乎传播更广,对于很多应用领域也更加适用。我什么时候用Python?
  • 网络开发
  • 科学计算和数据分析
  • 系统管理和工具
  • 游戏或3D应用程序脚本
  • 跨平台支持
不错的Python代码:
from itertools import islice

def hamming2():
    '''\
    A text documenting this function (stripped)
    '''
    h = 1
    _h=[h]    # memoized
    multipliers  = (2, 3, 5)
    multindeces  = [0 for i in multipliers] # index into _h for multipliers
    multvalues   = [x * _h[i] for x,i in zip(multipliers, multindeces)]
    yield h
    while True:
        h = min(multvalues)
        _h.append(h)
        for (n,(v,x,i)) in enumerate(zip(multvalues, multipliers, multindeces)):
            if v == h:
                i += 1
                multindeces[n] = i
                multvalues[n]  = x * _h[i]
        # cap the memoization
        mini = min(multindeces)
        if mini >= 1000:
            del _h[:mini]
            multindeces = [i - mini for i in multindeces]
        #
        yield h


Ruby

    Rails框架下的Ruby。这是它能登上这个列表的唯一原因。当然,现在其他框架下的Ruby很常见,但一切都从Rails开始。在那以前,Ruby只是日本来的晦涩编程语言。厉害的应用或者框架能催生庞大用户群,用户群能反过来产出更多厉害的应用或者框架,使本来会失去立足之地的语言变得流行,Ruby就是一个最好的例子。
    我听很多用Ruby的程序员说过,自己也有体会,Ruby的乐趣在于用。换句话说,它与那种让人丧气的语言正相反,不过我不确定这来自于语言本身还是Rails。 metasploit的工作人员似乎 一开始就十分明确这一点。
这是刚才的Python算法用Ruby写的结果。方法不同,也显示了Ruby更为函数式的风格倾向。
hamming = Enumerator.new do |yielder|
  next_ham = 1
  queues = { 2 => [], 3 => [], 5 => [] }

  loop do
    yielder << next_ham   # or: yielder.yield(next_ham)

    [2,3,5].each {|m| queues[m]<< (next_ham * m)}
    next_ham = [2,3,5].collect {|m| queues[m][0]}.min
    [2,3,5].each {|m| queues[m].shift if queues[m][0]== next_ham}
  end
end

idx = 1
hamming.each do |ham|
  case idx
  when (1..20), 1691
    p [idx, ham]
  when 1_000_000
    p [idx, ham]
    break
  end
  idx += 1
end

Scala

似乎在所有基于JVM的语言中一枝独秀。我确信,和主要竞争者之一Clojure相比,Scala大部分的优势来自于熟悉的语法。和Clojure一样,这种语言进入这个名单是因为能和Java轻松地结合,因此适用于实际项目。下面这个小片段生成了Hofstadter Q序列:

object HofstadterQseq extends App {
  val Q: Int => Int = n => {
    if (n <= 2) 1
    else Q(n-Q(n-1))+Q(n-Q(n-2))
  }
  (1 to 10).map(i=>(i,Q(i))).foreach(t=>println("Q("+t._1+") = "+t._2))
  println("Q("+1000+") = "+Q(1000))
}

Scheme

这种语言进入这个名单很可能有争议,但我有自己的理由。这个语言主要有三个问题:
    1.缺乏一种真正好的实现方法,以及若干稍逊色的竞争者
    2.库太少
    3.性能不佳
    第一点并不完全正确:实现方法太多了,但好的实现方法数量有限,你得选择最适合的那种。第二点也不完全对:库是有的,但太分散。 有许多大大小小的项目可提供替代品。查看支持代码时这种语言的分散性凸显:你得用自己的方法实现。不过,这通常并不难,耗时也不多,更重要的是,只要使用有良好FFI支持的Scheme实现方法(比如Gambit和Chicken Scheme),就能轻松获取C语言的所有库。我真的会 这么做,而且和你可能想象的不同,效果很好。最后,糟糕的性能。这一条完全错误。Gambit之类的实现速度很快,还有许多优化选择(包括算法优化,全局Scheme编译器声明,当然还有,有需要时轻易就能把C和Scheme结合)。
    是的,我是Scheme是狂热爱好者,但是,我承认它有一个致命的弱点:它的共享度很烂,因为用户群不怎么样。它如此灵活,面对一个任务,每个程序员都想得出自己的完美解决方案。这点和Java完全相反:Scheme很适合个人或者小团队项目,进行原型开发和探索性编程,在大型团队中的作用未经证明。但在适用情况下非常好,开发体验极为快捷、愉悦。最后,这种语言还有一个非常有意思的特点:使用Scheme-to-Js编译器很容易编译为Javascript,让你享受到和用Node.js在服务器上开发一样的对称性。以下是我选择Scheme的几种情况举例:
  • 没有确切目标的探索性编程
  • 为一个目标快速进行原型开发且不需要大型库(Python和Ruby中才有的那种)
  • 为C或C++的大型程序或者平台写脚本时
  • 编写需要大部分从头写起的应用程序时
  • 做游戏或者基于OpenGl/ES的多平台应用程序
下面是三个Scheme代码示例。这些函数需要自己来实现,因为在所有实现里没有现成的,不过它们依然常见而有效。适用于所有实现里(前提是兼容R5RS)。

;;! Recursive map that applies function to each node
(define (map** f l)
  (cond
   ((null? l) '())
   ((not (pair? l)) (f l))
   (else
    (cons (f (map** f (car l))) (f (map** f (cdr l)))))))

;;! Explicit currying of an arbitrary function
(define (curry fun arg1 . args)
  (if (pair? args)
      (let ((all-args (cons arg1 args)))
        (lambda x
          (apply fun (append all-args x))))
      (lambda x
        (apply fun (cons arg1 x)))))

;;! Implementation of filter, with the match macro
(define (filter p lst)
  (match lst
   ('() '())
   (((? p) . tl) (cons (car lst) (filter/match p tl)))
   ((hd . tl) (filter/match p tl))))
再看看其 他有趣的例子吧。
    不管是自力更生还是借助 Scheme Spheres等工具,如果你解决了极小型开发框架的问题,你就了不得啦。

恐龙级语言

    这种语言无所谓好坏。它们似乎被遗忘了,远离话题的中心,也没有什么理由吸引我们去使用。不过也许我们错了!

Assembly

  现在 没有人真的用Assembly编程了,连优化都用不到,因为编译器可以做得更好。没错,总有人比编译器更厉害,但我想那样的人必须非常非常聪明,而且知识渊博。
    但是,有一个重要的理由使你必须使用它:终极编程体验。使用SICP和各种Lisp语言能让人茅塞顿开,但我相信,最无以伦比的醒悟来自于真正理解所有这些语言的归宿:仅仅是一串处理器指令,不管是声明式语言,还是逻辑式、函数式、面向对象语言,都抽离于它们的高层体系结构之外。Assembly属于伟大语言之列。什么时候使用?
  •  学习时
  •  需要用到Assembly的系统开发
  •  对某个体系结构非常熟悉,并且需要手写其中一部分代码时

Common Lisp

    我用过Autolisp给AutoCAD做优化,但要是在Lisp、Scheme、Clojure中做选择,我选择Scheme。对我来说,它在三种还不错的Lisp语言中排名第三。它感觉有些臃肿,缺少Lisp的精髓:美感,优雅和简约。我会用它做快速原型开发,比起Scheme,它的优点是拥有现成的库,但Scheme会在这方面迎头赶上。另外,原型开发方面,还有更好的、同样拥有库的语言。

Perl

    有人写过美妙的歌曲来赞美Perl。显然是一个具有宗教性质的语言,它拥有自己的僧侣和预言家。它的创造者是语言学家Larry Wall,可以看得出他的特质投射到了这一语言中。它真的很让我着迷,就像编程语言里的拉丁语。同志们,行业里的高人依然在谈论Perl,一定有其道理。Larry的一句箴言说出了Perl的精髓:“真正的程序员能用任何语言写出汇编语言”。
    总的来说,Perl的语言学概念可以说令我赞叹。但它的语法有些怪异,用得不对就可能产生很糟糕的结果(和Lisp的宏十分类似)。我认为这种语言十分适合解决小问题,非常方便:它有很全面的库(CPAN),几乎有求必应,使得解决问题无比的简单。使用Perl的最糟结果,是为了写系统脚本而掌握了一样宝贵的工具。PS:有人告诉我Perl的对象支持烂极了,但在我看来这是个优点(也许我偏激了),不过我也怀疑这个论断的真实性。
  看看这两个伟大的作品: POE(用于反应式系统、合作多任务处理和网络应用程序的框架)和 Mojolicious,一个实时网络框架。
  BASIC, COBOL, Fortran, Pascal, Visual Basic…
  如果你需要使用这些语言中的任意一个,上帝都会保佑你的。他们应用在非常特定的领域(像Fortran,用于天文学和高性能计算,或者COBOL,用于银行等行业的庞大古老的系统),但它们几乎都受到程序员们的一致抨击。为什么要用它们?我给你一个很好的理由:维护别人代码就能赚到相当滋润的时薪。自己来写?想都别想:)

  Smalltalk

  第一个真正的面对对象语言,但在我看来它基本上已经被遗忘了。
  不可理喻的语言
  用于生产目的时也许不可理喻,但它们绝对能促使你成为更优秀的程序员(这完全合理)。到底什么有意义,选择权在你。我能说什么呢,我喜欢不可理喻的选择。

  Array, J

  这是我要学的语言,因为我听说它们有特色,能使人思维开阔,超越函数式和声明式语言的限制。

  Factor, Forth

  基于堆栈的语言是非常强大,值得学习。对扩展思维有益。已经加入我的目标列表。

  F#

  这是微软扮酷的尝试。语言不错,但是我们大多数人已经得到过惨痛的教训,要远离微软。公司赞助的语言已经够多了。

  Oz

  这是一种典型的多范式语言,带有约束和分布式编程功能。它拥有主流编程语言如函数式(即懒惰又有野心)、命令式和面向对象语言的大部分特点。

  Prolog/Datalog

  声明式逻辑语言总体上来说非常学术派。不过也有一些例外,可以在 这个Stackoverflow提问里看到,Scheme也可以说是一个例子。

  Rust

  Mozilla在系统编程语言界的竞争者。它没有D一样的悠久历史,也不像Go一样有Google这种大公司支持。不过,我仍然希望看到Rust在未来成为系统开发的合理选择之一。
  Shen
  它进入这个名单,是因为我读到过Shen里有可更换皮肤的类型系统和其他新颖有趣的点子。然而,它的实现还处在试验阶段,语言的许可证让人无法接受。它的创造者似乎生活在另一个时代。

  TCL

  我用过几个月,那时我急需同像性的、绑定了我当时需要的库(BRL-CAD)的语言。我认为这种语言被低估了,但被低估的语言还有很多。而且它没有特酷的功能作为闪光点(像Erlang那样)。


  结论

  我以我选择的语言开始了这个漫长的帖子。编程是美妙的艺术,我全身心喜欢它,所以我承认个人经历给我造成了很强的偏向性。由于太多的不确定因素,选择编程语言有时很困难。以我的观点看,有三个因素首当其冲,顺序如下:
  1. 项目是否以产品生产为目标,是否属于一个拥有文化底蕴的大型组织,是否倾向于某一编程语言?
  2. 当前任务是否特殊到需要某一编程语言的特定功能?
  3. 你喜欢或者是想要尝试用这种语言编程吗?
  这是我处理这个问题的方法。尽管有时候会打破规则……

你有更能代表这些语言特点的代码片段吗?


本文经原作者许可翻译,未经许可禁止转载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值