Lisp可以完成哪些其它語言難以實現的功能?最好能夠舉一些例子

網上有很多說Lisp很強大很靈活的,但是都沒有具體給出例子,難以理解。


準時下班。

ps:我真的不騙你。


謝邀

Lisp 與非 Lisp 語言最大的不同恐怕要算他是一個可編程的編程語言。

Lisp 可以用代碼生成代碼、給 Lisp 添加新語法。你可以分分鐘就用 Lisp 寫出一種新的編程語言出來。這讓 Lisp 非常適合進行元編程,我們一般寫代碼的過程是先弄清問題,然後設計相應的數據結構,最後編寫操作數據結構的代碼。無論你用什麼高大上的語言基本都是這個思路。元編程的思路完全不同,它是針對特定問題領域先發明一種新的編程語言,然後用這個語言解決這個領域的具體問題。這種編程方法強大到什麼程度?舉個栗子:比如 HTML 就是一種專門用於編寫網頁的語言,很少的代碼就可以寫出有漂亮排版的頁面來,同樣的頁面讓你用C++、Java 這種語言去編寫需要多久?前者的開發效率可能是後者的上百倍。

如果你遇到一個很新的問題領域,沒有合適的語言表達它,那你可能自己發明一種語言出來(發明新語言沒你想的那麼難),用一般的編程語言實現一種新語言是很難的,而 Lisp 天成就有這種能力。餓了,例子就不舉了,如果感興趣可以看看維基百科:元編程


Lisp 的宏讓你可以自己動手擴展語言而不必等標準委員會漫長的流程。

比如你可以自己實現指針……

; Making a pointer -- a corresponding Scheme closure, to be precise.

; The original paper had the following low-level macro
;(define-macro ( x)
; `(lambda (action)
; (case action
; ((ref) ,x)
; ((set) (lambda (new-val) (set! ,x new-val))))))

; The same macro as a syntax rule
(define-syntax
(syntax-rules ()
(( x)
(lambda (action)
(case action
((ref) x)
((set) (lambda (new-val) (set! x new-val))))))))

; Dereferencing the pointer to an R-value

(define (p-ref ptr)
(ptr "ref))

; Dereferencing the pointer to an L-value and updating the pointed
; variable

(define (*= ptr)
(ptr "set))

; Overloading the * operation with C-style dereferencing
; so we could write (* p) rather than (p-ref p)

(let ((old-* *))
(set! *
(lambda args
(if (and (pair? args) (null? (cdr args)) (procedure? (car args)))
(p-ref (car args))
(apply old-* args)))))


Lisp的優點只有一條,就是其eval無須parse input,同時構造eval的input的方式也被簡化到了極致

因此可以說Lisp是最適合meta-programming的語言

除開這點,Lisp和其他語言並無本質分別


你沒見過具體例子是因為根本就沒有這樣的例子。

lisp 沒那麼神。只有兩種人會以為 lisp 神。一種是只看軟文,如黑客與畫家,的人,一種是對 lisp 和編程都一知半解的人。這兩種人都以為 宏 能怎樣怎樣。


lisp 確實強大,但是在工廠模式下的開發, 不是很適合規劃化作業, 因為代碼的性能,表達,語法,是程序員自己決定,在沒有嚴格的開發規範的約束下,代碼很難維護,

還有,在一般應用領域,lisp 並沒有多大優勢。


「誒,這個功能不錯,可是 Lisp 里沒有,我用宏實現看看……搞定!」


用lisp就是把自己變成人肉編譯器


「在讀取期編譯或運行代碼,也可以在編譯期讀取或運行代碼,還可以在運行期讀取或者編譯代碼。「


可以參看《黑客與畫家》的附錄,《編程能力》,摘錄如下:

為了解釋我所說的語言編程能力不一樣,請考慮下面的問題。我們需要寫一個函數,它能夠生成累加器,即這個函數接受一個參數n,然後返回另一個函數,後者接受參數i,然後返回n增加(increment)了i後的值。

Common Lisp的寫法如下:

  (defun foo (n)
    (lambda (i) (incf n i)))

Javascript的寫法稍微長一點,因為Javascript依然區分語句和表達式,所以你需要明確指定return語句,來返回一個值:

  function foo (n) {
    return function (i) {
      return n += i } }

Python高手看來也同意,這是解決這個問題的比較好的方法,寫法如下:

def foo (n):
    class acc:
      def _ _init_ _ (self, s):
        self.s = s
      def inc (self, i):
        self.s += i
        return self.s
    return acc (n).inc

Ken Anderson說,Java只能寫出一個近似的解法:

  public interface Inttoint {
    public int call (int i);
  }
  public static Inttoint foo (final int n) {
    return new Inttoint () {
    int s = n;
    public int call (int i) {
    s = s + i;
    return s;
    }};
  }

這種寫法不符合題目要求,因為它只對整數有效。

完整版在這裡:為什麼Lisp語言如此先進?(譯文)


推薦閱讀:

函數式語言中如何實現while true?
學習 LISP 有哪些網站或書籍推薦?
如何評價 Racket 這門編程語言?
為什麼著名的輪子很少有用 Lisp 寫的?
精通 Lisp 是一種怎樣的體驗?

TAG:編程語言 | 函數式編程 | Lisp | CommonLisp |