什麼是最好的程式語言?(怎樣才能愛上程式設計呢?)

ourjs發表於2014-03-11

  經常有人會寫點評論程式語言的文章,可能是一些很古老的快被遺忘的語言,也可能是正在流行的新語言。現在我也要寫點什麼,寫出了我對程式語言的一些想法。

  免責宣告:除非你精通三十門以上的語言並且能夠很好地用他們程式設計(或者是其中的絕大部分),否則你不能客觀地評價這些語言的好壞。是的,就像其他人寫的關於這方面的文章一樣,我也有自己的偏好。事實上,我認為如果你精通很多門語言,你就會認為這個話題是多麼的荒誕可笑。

  下面這些就是在我的部落格中被評為最偉大的語言:

  • 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)。我想說的這是一種像其他很多語言一樣被低估的語言。它也沒有什麼特別好的前途。

  結論

  我以我選擇的語言開始了這個漫長的帖子。程式設計是一個很美妙的藝術,我真心喜歡它,我承認我偏向於使用自己的經驗寫這篇文章。由於太多的不確定性,選擇一種語言來程式設計是一個很困難的事情。以我的觀點看,有三點很重要:

  • 這個工程的目的是為了創作出一個產品,還是屬於一個擁有文化底蘊的組織而偏向於某一種語言嗎?
  • 這項任務非常特殊而就是要求某一程式語言嗎?
  • 你喜歡或者是想要盡力用這種語言程式設計嗎?

  儘管有時打破這個規則,但這就是我解決這類問題的方法。

  你有更好的程式碼片段顯示這些語言的特點嗎?

  原文 blog.fourthbit.com

相關文章