什么是最好的编程语言?(怎样才能爱上编程呢?)


发布者 renyuzhuo  发布时间 1394342459000
关键字 大话编程 
经常有人会写点评论编程语言的文章,可能是一些很古老的快被遗忘的语言,也可能是正在流行的新语言。现在我也要写点什么,写出了我对编程语言的一些想法。

免责声明:除非你精通三十门以上的语言并且能够很好地用他们编程(或者是其中的绝大部分),否则你不能客观地评价这些语言的好坏。是的,就像其他人写的关于这方面的文章一样,我也有自己的偏好。事实上,我认为如果你精通很多门语言,你就会认为这个话题是多么的荒诞可笑。

下面这些就是在我的博客中被评为最伟大的语言:

  • Assmbly:机器语言
  • C:形式化语言
  • Javascript:网编编程语言
  • Scheme:与C和Javascript相比,更轻巧,嵌入性更好,是极其灵活的编程语言

范例程序来自Rosetta Code

合适的语言

我不把这些语言称之为合适的语言(reasonable languages)是因为他们是最好的语言(best languages)。他们是现在人们普遍使用的编程语言,人们用他们来编写软件。当然了,你可以避免这些争论而是自己去做决定,如果那样的话,进入下一部分吧。

Ada

我总是对一种语言存储安全的方面很好奇。大体来说这对于真实的操作系统和普通的一般的应用系统都是很有意义的。如果你有相关专业背景的话,并且使用这种语言的话,你不需要读下面的这一部分,但这是一种一旦你知道你需要用它来做什么,你就没有什么选择余地的语言。Ada代码:
  function Best_Shuffle(S: String) return String is
T: String(S'Range) := S;
    Tmp: Character;
  begin
    for I in S'Range loop
      for J in S'Range loop
        if I /= J and S(I) /= T(J) and S(J) /= T(I) then
          Tmp  := T(I);
          T(I) := T(J);
          T(J) := Tmp;
        end if;
      end loop;
    end loop;
    return T;
  end Best_Shuffle;
看起来很安全,不是吗!:)

Bourne (Again) Shell

我经常考虑,难道我真的需要用shell来写Linux脚本吗?真的有必要吗?如果你不用shell写script(脚本)也没有关系,因为最终你要面对面的处理这些script,并且你还要考虑怎样在Bare Metal Age和pre-stackoverflow中处理这些问题。这种语言没有什么令人吃惊的地方,也没有什么可以扩展你的思维或让你更有创造性的特性,也难以从应用的业务角度去证明它是好的。也许仅在不知道什么情况中才可以体现出来吧。然而他在系统管理中是那么重要,并且没有看起来那么糟糕。就像是Javascript,你需要比其他语言更多的实践练习。
为什么我要用Unix Shell呢?
  • 我是OSX/Linux/POSIX系统管理员
  • 为了实现自动化
  • 为了使用命令行的强大功能
一些Bourne Shell代码。享受这些布尔表达式吧!
			#!/usr/bin/env sh
l="1"
while [ "$l" -le 5 ]
 do
 m="1"
 while [ "$m" -le "$l" ]
   do
   printf "*"
   m=`expr "$m" + 1`
 done
 echo
 l=`expr "$l" + 1`
done

C

尽管你可能不喜欢C语言,但你必须要尊重它。他可能是最伟大的语言之一。他能真正地能编写系统级代码。它是UNIX的制造者,是所有语言的鼻祖,是通用的系统级编程语言。它久经沙场,经历时间的检验,广泛传播。太多的开发,调试,性能分析工具支持着C的发展,这也使得它减少了作为语言的缺陷(我看来,这些缺陷不多)。这是一个真正实现了其目标的语言:成为通用的语言。今天,它甚至形成了最奇怪的一个体系结构,这也使得今天很难手写出比C编辑器编译出的代码更好的代码。
尽管有这么强大的工具,但这是需要被人掌握的。这种语言很是冷酷无情,你需要懂它知道你自己在用它干什么。理解机器内部对C语言很重要,C语言可以控制机器的底层。这一点很好,有积极的一面:如果没有C语言这样的底层语言,有些事情我们做不到。C语言程序员必须要彻底理解他们自己在干什么,这一点对于长时间运行的可靠的软件是极为重要的。如果有什么事物可以分开,C语言可以很好地支持并发。C语言编写的程序运行时的效率和C语言的普遍性是一个神话!
Linux内核中的C语言代码:
		int next_pidmap(struct pid_namespace *pid_ns, unsigned int last)
{
   int offset;
   struct pidmap *map, *end;
   if (last >= PID_MAX_LIMIT)
       return -1;
   offset = (last + 1) & BITS_PER_PAGE_MASK;
  map = &pid_ns->pidmap[(last + 1)/BITS_PER_PAGE];
  end = &pid_ns->pidmap[PIDMAP_ENTRIES];
  for (; map < end; map++, offset = 0) {
      if (unlikely(!map->page))
          continue;
      offset = find_next_bit((map)->page, BITS_PER_PAGE, offset);
      if (offset < BITS_PER_PAGE)
          return mk_pid(pid_ns, map, offset);
  }
  return -1;
}

C++

这是一个奇怪的东西。它是我接触的第一种语言,并且我真的不知道他怎样的限制住了我的生产力并限制了我的技术直到我尝试了其他的语言。c++的坏名声是被一些著名的程序员造成的,我完全同意。C++看起来仿佛是Bjarne Stoustrup把他能想到的所有的功能都加到C中。学习掌握它的负担,使你的编程效率降低80%以上。这样考虑:你的大脑容量是X,容量有限,不管你有多少的能力,你想留下尽可能多的重要的事情。明智的做法是减少用于语言本身的脑力劳动,而是使用大脑和优化的算法。如果语言复杂,无论你有多聪明,你都要用更多的脑力用于解决这语言的语法和语义上的问题,这会使你使用更少的时间用于优化你的代码。
我认为C++是典型的例子,太复杂的事物没什么意义。我同意,用C编写大的程序是困难的(但是有例外,看Linux内核)。通过这些分析,Go,Rust和D语言似乎是更好的,但事实是C++在世界范围内却被广泛地应用。
这是一个很好的C++使用模板,以下面的方式使用C++更容易理解,而不是使用template/classes来定义。
	#include
#include
#include
int main( int argc , char** argv )
{
   int linecount = 0;
   std::string line;
   std::ifstream infile( argv[ 1 ] );
   if( infile )
   {
       while( getline( infile , line ) )
       {
           std::cout << linecount << ": " << line << '\n';
           linecount++;
       }
   }
   infile.close();
   return 0;
}
接下来是一些模板代码,一个很简单的例子,(产生出很糟糕的代码)
		namespace rosettacode
{
 template class queue
 {
 public:
   queue();
   ~queue();
   void push(T const& t);
   T pop();
   bool empty();
 private:
   void drop();
   struct node;
   node* head;
   node* tail;
 };
 template struct queue::node
 {
   T data;
   node* next;
   node(T const& t): data(t), next(0) {}
 };
 template
  queue::queue():
   head(0)
 {
 }
 template
  inline void queue::drop()
 {
   node* n = head;
   head = head->next;
   delete n;
 }
 template
  queue::~queue()
 {
   while (!empty())
     drop();
 }
 template
  void queue::push(T const& t)
 {
   node*& next = head? tail->next : head;
   next = new node(t);
   tail = next;
 }
 template
  T queue::pop()
 {
   T tmp = head->data;
   drop();
   return tmp;
 }
 template
  bool queue::empty()
 {
   return head == 0;
 }
}

C#

这种语言旨在减少代码,增加复用性,从而提高程序员的创造性。它是面对对象,具有静态类型,有大量的库函数。你能看出它是微软由控制的。但点我不会担心,它不是一个糟糕的语言。它不是很吸引人,也许微软真正想要的就是准确性吧。相比VB这是一个过于激进的改变吧。我能使用它来做的事:
  • windows编程
  • 游戏开发(大多数是由于微软的强迫而使用它,我认为C/C++更好)
  • 这种语言能做大量的事情:Unity3D, Xamarin, .NET, XNA。
下面是一些代码:
	using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Program
{
   static SortedDictionary GetFrequencies(IEnumerable items)
   {
       var dictionary = new SortedDictionary();
       foreach (var item in items)
       {
           if (dictionary.ContainsKey(item))
           {
               dictionary[item]++;
           }
           else
           {
               dictionary[item] = 1;
           }
       }
       return dictionary;
   }
   static void Main(string[] arguments)
   {
       var file = arguments.FirstOrDefault();
       if (File.Exists(file))
       {
           var text = File.ReadAllText(file);
           foreach (var entry in GetFrequencies(text))
           {
               Console.WriteLine("{0}: {1}", entry.Key, entry.Value);
           }
       }
   }
}
是否发现与Java很像呢!

Objective-C

相比C++和C#,对于Objective-C,我有更多的想法。他的语法很不好,但是作为语言我喜欢它。他有基于NextStep的一套很好的库函数,这些库函数的增加,让C有很大的进步。它没有增加比其它父语言太多的难以控制模棱两可的关键字。正如我说的,它的代码有一点复杂并且很难阅读,尤其是对于嵌套函数更是如此。但在概念方面,有一些很好的东西,而不是其语法上。看这个代码嵌套调用:
		char bytes[] = "some data";
NSString *string = [[NSString alloc] initWithBytes:bytes length:9 encoding:NSASCIIStringEncoding];
对于C语言衍生出来的这个漂亮的代码,利用了C语言的所谓的“block”。

#import
typedef NSArray *(^SOfN)(id);
SOfN s_of_n_creator(int n) {
 NSMutableArray *sample = [[NSMutableArray alloc] initWithCapacity:n];
 __block int i = 0;
 return ^(id item) {
   i++;
   if (i <= n) {
     [sample addObject:item];
   } else if (rand() % i < n) {
     sample[rand() % n] = item;
   }
   return sample;
 };
}
int main(int argc, const char *argv[]) {
 @autoreleasepool {
   NSCountedSet *bin = [[NSCountedSet alloc] init];
   for (int trial = 0; trial < 100000; trial++) {
     SOfN s_of_n = s_of_n_creator(3);
     NSArray *sample;
     for (int i = 0; i < 10; i++) {
       sample = s_of_n(@(i));
     }
     [bin addObjectsFromArray:sample];
   }
   NSLog(@"%@", bin);
 }
 return 0;
}

Clojure

作为一个Scheme程序员我尊重Clojure:是所谓的现代Lisp,他有一些独特的特性。我想说Clojure在编程方面的长处是和Java语言相同的互操作性和并发实用程序。它与scaling是紧密相关的,但他们的特点是不同的:lisp是面向对象和面向过程的混合,Clojure有过多的括号而使其没有lisp流行。选择这两种语言中的哪一个进行编程取决每个人不同的风格,这是因为没有长期的记录说明哪一个在编程方面更成功一点,就像Java与PHP相比,虽然他们都是运行在虚拟机上的。对于任何基于虚拟机运行的语言,另一件需要考虑的事情是运行时间:这与很小的小程序是不同的。这是一些我用Clojure所要解决的问题:
  • 网络编程。对于网络编程,这是一个很好的选择,在这个领域Clojure看起来是十分流行的。
  • 当你想使用JVM而没有Java技术时。程序员的快乐程度和生产率都将提高。
  • 探索性的编程,编出的代码能修改成产品代码。这一部分Lisp也做的很好,但是Clojure是基于Java的,其有许多代码时开源的。
  • 安卓程序开发?安卓程序开发的GUI模式很大程度是基于类继承。(意味着你不仅仅确切地使用它作为一个插件库,而是迫使你使用某些结构)。这个可以实现,但是这又不像Java继承那样自然。
经典的Clojure代码:
		(defn divides? [k n] (= (rem n k) 0))
(defn prime? [n]
 (if (< n 2)
   false
   (empty? (filter #(divides? % n) (take-while #(<= (* % %) n) (range 2 n))))))
Lisp形式的队列的定义代码:
(defn make-queue []
 (atom []))
(defn enqueue [q x]
 (swap! q conj x))
(defn dequeue [q]
 (if (seq @q)
   (let [x (first @q)]
     (swap! q subvec 1)
     x)
   (throw (IllegalStateException. "Can't pop an empty queue."))))
(defn queue-empty? [q]
 (empty? @q))
 

D

我以前很喜欢D,D恰好就像C++一样做的很好。D1很像底层的Python。很像pythonized C或者是类似的东西。真是了不起:你感觉到了其发展迅速吧,他专注于算法而不是语言,但当你需要控制底层时,它又没将这一部分去掉。D2带来了C++的一些复杂性,这是由于Andrei Alexandrescu的创新。这使得一部分人不高兴了,虽然其确实在并发性方面做得更好了。D2再也不是一个纯粹的语言了。尽管我喜欢它,但是我还是感觉其不如C++普遍(一旦其复杂起来)。并且我认为现在Go正在吞并D的市场。尽管在语言方面真的能更快一些、更酷一点,但Walter和Andrei不能与google竞争。你可能正如我一样喜欢D,但是我不是很看好它。仅仅是追随C++或者是按照GO语言更加支持本地并发开发呢。我什么时候会使用D语言呢?
  • 从头开发一个项目时,与C有接口或者是与C++有联系时。你需要提前想好接口是什么样子的。对于接口,我不建议使用C++的GUI,因为其要从内部处理C++的继承,这将使得其优势发挥不出来。如果需要,就简单做一个插件库吧。(创建对象,使用其功能,而不是模板或是C++的继承)
  • 底层二进制的编程。就像一个独立的部分,做自己的事情。
  • 如果希望能很好地支持并发。
让我们看一些D2的惯用法,纯函数,不可变的声明。
		uint grayEncode(in uint n) pure nothrow {
   return n ^ (n >> 1);
}
uint grayDecode(uint n) pure nothrow {
   auto p = n;
   while (n >>= 1)
       p ^= n;
   return p;
}
void main() {
   import std.stdio;
   " N     N2      enc     dec2 dec".writeln;
   foreach (immutable n; 0 .. 32) {
       immutable g = n.grayEncode;
       immutable d = g.grayDecode;
       writefln("%2d: %5b => %5b => %5b: %2d", n, n, g, d, d);
       assert(d == n);
   }
}
表的最大元素:
		[9, 4, 3, 8, 5].reduce!max.writeln;
截止至今,其是比C++更具有表达性和更清洁的语言。

Erlang

这是一个有目的性的语言。Erlang的web界面是非常清晰的:构建大规模可伸缩软实时的或可用的系统。它使用在电信、银行、电子商务、计算机电话和即时消息等方面。他的实时性也支持并发,分布和容错。其在一些要求很高的应用程序中已经得到证明,例如WhatsApp。其代码很有效,含义清晰,很可读。
看一下简单的并行程序的一个小例子:
		-module(hw).
-export([start/0]).
start() ->
  [ spawn(fun() ->  say(self(), X) end) || X <- ['Enjoy', 'Rosetta', 'Code'] ],
  wait(2),
  ok.
say(Pid,Str) ->
  io:fwrite("~s~n",[Str]),
  Pid ! done.
wait(N) ->
  receive
      done -> case N of
          0 -> 0;
          _N -> wait(N-1)
      end
  end.

Go

我没有亲自使用过它。但很显然的是,这是google做的,其将C与C++好的部分加在一起并且在并发方面比他们都好的语言。它比C++有更好的部分,它形式简单。他没有不安全的指针,拥有包特性、函数和垃圾收集机制。未来Go可能成为服务器端语言。我什么时候要试试Go呢?
  • 对于服务器应用程序,需要非常高的可靠性和性能。这包括web应用程序。
  • 对于控制底层的高效率的代码(然而,我更喜欢Erlang)
Go的并行程序代码
		package main
import (
   "fmt"
   "math/rand"
   "time"
)
func main() {
   words := []string{"Enjoy", "Rosetta", "Code"}
   rand.Seed(time.Now().UnixNano())
   q := make(chan string)
   for _, w := range words {
       go func(w string) {
           time.Sleep(time.Duration(rand.Int63n(1e9)))
           q <- w
       }(w)
   }
   for i := 0; i < len(words); i++ {
       fmt.Println(<-q)
   }
}

Haskell

比起这个表单上的其他语言,这种语言更像是一种工具。几乎在任何用代码实现起来有困难的地方,都提供了函数库。可以说这是一种很高门槛的语言。我看来,他考验你的大脑,在各种社区中有一群最聪明的人。我认为Haskll是很值得学习的,尽管你也许不能用它编写任何程序。作为相对来说比较模糊的语言,我这样定义它是很合理的,并且在一些方面还是很有用的,例如金融方面。Haskell的代码往往是非常紧凑的,但在某种意义上来说,虽然有点抽象,你需要很多的函数,实际上是概念上的操作,而不是一步一步那样去执行的。我个人不喜欢它的语法(我认为其语法太复杂),但至少它服务于一个目的,不觉得混乱。(我把你看成了Perl!),这种语言看起来漂亮连贯,自己看吧:
binarySearch :: Integral a => (a -> Ordering) -> (a, a) -> Maybe a
binarySearch p (low,high)
  | high < low = Nothing
  | otherwise =
      let mid = (low + high) `div` 2 in
      case p mid of
        LT -> binarySearch p (low, mid-1)
        GT -> binarySearch p (mid+1, high)
        EQ -> Just mid

Java

看起来很像是C#,但是他有虚拟机。它是第一个(C#仿照它)面向对象的语言。除了嵌入式设备不行和极其要求性能的地方不行,它几乎什么都能干,web app到游戏。它是许多其他语言的基础,尤其是虚拟机方面。看一个有趣的项目,它是为了教育、数学和艺术的而写的程序。我什么时候要用Java呢:
  • 主要是当你想访问一个非常大的开发商,即你想要别人维护你的软件。
  • 当你需要在尽可能多的硬件上跑你的程序。
Java7的例子程序,看吧:
		import java.util.List;
import java.nio.charset.Charset;
import java.nio.file.*;
public class ReadAll {
   public static List 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的编译器中。这实际上证明了社区是极其伟大的(如果不是最大的)语言来支持者。有趣的是,你会看到无数的库在做同样的事情,这使得库成为竞争最激烈的领域之一。看Grunt、Gulp等,真是太疯狂了。
下面的代码显示了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
   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的细节的话(就像例子中一样),你会我发现将两种风格混合在一起很酷。

OCaml

它有几分像Haskell,但更能满足程序员的想法。如果需要的话,一些取舍会使问题更容易解决。面对对象的方法看起来更容易工作。有人使用他,我估计就是他在这一点上超过了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,对不对?

PHP

不要怕PHP,调整好看PHP的心态,如果你喜欢PHP编程,那你就成为了真正的程序员。这是一种代价小的语言。什么时候使用呢:
  • 如果想要大量的web开发人员一起工作
  • 就是它,没什么原因
  • 下面是漂亮的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。但这也是不同于其他语言的地方,因此许多人也因为这个原因不喜欢这种语言。这是一种清楚的语言,减轻了你肩上的语法的负担。尽管在这一方面是很有争议的,但是还是有大量的人坚决支持这种语言。在很多情况在这两种语言中选择的是很难的,对于各种应用领域尽管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

Ruby来自Rails。这个简单的原因就可以使它不在这个列表中。当然了,现在可以看到许多其他的程序,但都是来自于Rails。在那以前,Ruby是一种来自日本的很难理解的语言。这是一个对于鼓励快要消失的编程语言成为极其流行的语言的很好的例子。
我以前从许多Ruby程序员那里听到,当然我也是一个很熟练的Ruby的程序员,他们说这是一个令人愉快的语言。换一句话说,这是一个绝不会令人沮丧的语言,我不知道这是来自语言或者是Rail本身。很早以前就被metasploit(一篇文章)指出来了。
这是用Python写过的代码,这里用Ruby再写一遍。风格不同,体现出了Ruby更有“function”风格。
		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或其他大的流行的语言相比,它更是语法方面很简单。这种语言也在这个列表中的原因是其可与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

这种语言在这个列表中,会有很多人对此有争议,对此有三点理由:
  • 缺乏控制质量的方法
  • 很少有函数库
  • 性能不佳
第一点是确实的,对于解决问题你有许多方法,但是没有哪一个是首选的有效的方法。第二点也是真实的:有函数库,但是都是分散的。语言方面的分散使得需要寻找可供使用的代码是很显然的:你需要用你自己的方法实现。这也许不是十分困难或者是耗时的,如果你要使用带有很好的FFI支持的Scheme实现,例如Gambit或Chicken Scheme,你需要使用C语言的那些函数库。这与你可能想的相反,我是这样做的,并且能很好的工作。但最后,表现不佳。实际上这是完全错误的。像Gambit那样实现是非常快速的,并且你还能优化它。从算法优化,到全局模式编译器声明。当然了,C代码可以很容易地在必要的时候组织代码。
是的,我对于Scheme是狂热的。但是,我承认它有一个致命的弱点:对于共享代码,它太差了,只有一个不太好的社区。它是如此的灵活,以至于每一个程序员都希望自己能对于问题提出完美的解决方案。Java在这方面是完全相反的:Java社区中有杰出的个人或小团队,有试探形式的编程,未经证实的大型团队。但在这种情况下,是非常好的,你可以在一个非常快速和愉快的环境中发展。最后,语言的另一个非常有趣的特性:您可以很容易地用一个Scheme-to-Js编译器编译为Javascript,所以你可以享受在节点在服务器上编程的乐趣。以下是我使用这个语言具体的例子:
  • 需要快速编程且不需要只在像Python或Ruby中提供的库
  • 在C或C++平台的开发的脚本程序。
  • 为了构建一个需要从基础代码扩展出大部分代码的应用程序
  • 对于游戏和OpenGL/ES-based多平台的应用程序。
这是一个Scheme代码示例。虽然有函数库,但你需要自己去实现各部分功能代码,因为没有什么可用的。都要去实现:
		;;! 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))))
再看看" these other interesting examples"(一篇文章)吧!

Dinosaur languages

这种语言无所谓好坏。似乎我们仅仅是将其忘记了,没有什么特别之处,也没有什么理由吸引我们去使用这种语言。也许我们是错误的。

Assembly

事实上再也没有人用Assembly(汇编)真正编程了,因为编译器已经真的很好了,似乎也不用汇编来优化了。我认为总是有人可以用汇编写出极其优秀的代码,但那样的人必须是足够聪明的。
但是也有一个必须使用汇编的地方:终极编程。用SICP和Lisps对编程有特别好的启发,但是我相信如果从语言的最基本的地方理解也能得到启发:就像处理器指令序列,抽象的语言结构,无论是在声明,逻辑、功能或面向对象方面都有启发。对程序员的大脑有好处。这是一种伟大的语言。什么时候使用呢:
  • 为了学习
  • 系统级编程需要使用的时候
  • ·当你需要手工实现某些功能时

Common Lisp

我过去使用Autolisp、AutoCAD,但需要在Lisp、Scheme、Clojure中做决定时,我选择Scheme。对于我来说,在前面提到的三种语言中,它排名第三。它感觉起来有些复杂,没有了lisp中的美丽,优雅和简单。我会用它来进行快速建模,但现在已经拥有的库,使我们可以不用它解决问题。并且我认为有拥有更好的库的语言。

Perl

显然是一个具有宗教性质的语言,这种语言拥有自己的宗教团体。有这样一个事实是语言学家Larry Wall将创造性加入到这种语言中。感觉Latin真的是很迷人呀。伙计们,一定是有某些原因才使仍有很多杰出的人在讨论这种语言。这种语言的精髓被Larry写过的话描述了出来:汇编语言可以写出一起东西。
总的来说,我对Perl语言的概念有很深刻的印象。但其有趣的语法也可以导致产生出很多的错误(Lisp中很多地方使用宏)。我认为这种语言的伟大的是在解决小问题时非常方便:它有一个很全面的库(CPAN),提供了几乎任何你想要的方法,这使得解决问题很方便很简单。使用Perl可能出现的最坏情况是,为了改变你的系统,你要学习很多的东西。Ps:我已经被告知Perl的对对象支持是极其可怕的,但我认为这也是一个好处(我可能是偏激的),但我也怀疑这种说法。
看看这两大项目:POE(反应系统的框架、合作多任务处理和网络应用程序),和一个实时web框架Mojolicious。

BASIC, COBOL, Fortran, Pascal, Visual Basic…

如果你需要使用这些语言中的任意一个,上帝都会保佑你的。他们应用在特定的领域(像Fortran应用在在天文学上和HPC应用在社区中),或COBOL(在一些行业中的仍在使用的古老的系统),但它们几乎都被社区的人们一致抨击。但我给你一个很好的理由使用这些语言:当你维护别人代码时按小时收费。对于自己的代码呢?不讨论这些:)

Smalltalk

第一个面对对象的语言,但是对于我来说它似乎是被忘记了。

The Unreasonable languages

可能用于生产使用这种语言不太合理,但肯定会促使你让你成为更优秀的程序员(这是完全合理的)。你的选择是有价值的。我能说什么,我喜欢另类的观点。

Array, J

我有许多的语言需要学习,我听说他们是独特的并且学习他们将在除了语言和语法方面扩展你的思维。

Factor, Forth

基于堆栈的语言是非常有能力的并且是非常值得学习的。很能扩展你的思维。所以就在这张列表中了。

F#

这是微软想扮酷的想法。这是一个很好的语言,但是我们中有许多已经学会了远离微软了。我们有足够的其他公司出资的语言了。

Oz

这是一种非常规范的有约束力和可分布式编程的语言。它拥有大部分主要编程语言的特点(懒惰和渴望),命令式和面向对象的。

Prolog/Datalog

声明式逻辑语言大体上是非常具有学术性质的。不过也有一些例外,可以看到在this Stackoverflow question中被看到,并对与Scheme也是如此。

Rust

对于系统编程语言Mozilla的竞争者。它没有像D一样的历史,也没有像google这样的大公司的支持,仅仅像Go一样。不过,我仍然希望看到Rust在未来可作为系统开发的合理的选择。

Shen

它在这个列表中,是因为对其类型相关的东西,我读到了有趣的东西,一些非常基础和有趣的东西是用Shen写的。然而,它的实现是极其具有实验意义的,并且这个语言有一个不可接接受的许可证。这个语言的创造者似乎生活在另一个年代。

TCL

我过去几个月,这时我发现程序与数据由同样的结构存储并且它绑定到一个我需要了解的库,这些是问题(BRL-CAD)。我想说的这是一种像其他很多语言一样被低估的语言。它也没有什么特别好的前途。

结论


我以我选择的语言开始了这个漫长的帖子。编程是一个很美妙的艺术,我真心喜欢它,我承认我偏向于使用自己的经验写这篇文章。由于太多的不确定性,选择一种语言来编程是一个很困难的事情。以我的观点看,有三点很重要:
  • 这个工程的目的是为了创作出一个产品,还是属于一个拥有文化底蕴的组织而偏向于某一种语言吗?
  • 这项任务非常特殊而就是要求某一编程语言吗?
  • 你喜欢或者是想要尽力用这种语言编程吗?
尽管有时打破这个规则,但这就是我解决这类问题的方法。

你有更好的代码片段显示这些语言的特点吗?











回复 (6)
  • #
  • #1 小时光 1394619146000
    只有时间才会让你爱上编程!
  • #2 天若尘 1394721238000
    槽点太多,Java是第一门面向对象的?
  • #3 白弓匹 1422968850357

    C++才是第一门面向对象的吧?

  • #4 葛尖死 1423728943535

    文章太烂以至于不知道怎么吐槽,走人

  • #5 李大爷 1501488623489

    楼上sb

  • #6 sucaihuo 1511753058769

    跟我一起来看视频教程学习编程吧 http://www.sucaihuo.com/video

微信扫码 立即评论