精通 Lisp 是一種怎樣的體驗?
聲明:並非精通Lisp,只是有點體會。。
因為之前接觸的都是Basic,Visual Basic,C之類的。。大一看到Common Lisp時還是很驚艷的,然後入了函數式的坑。
其實吧,Lisp社區還是比較實用主義的,Clojure也用得挺廣泛了;Lisp並非」函數式原教旨主義」。Li傾向於多範式,比如,Common Lisp面向對象可是教科書式的multiple dispatch(多次被輪子哥鼓吹的東西。。)。
基本上,動態類型+函數式特性+List+S表達式,給了Lisp很大的自由,也導致Lisp很難有高效實現,難排錯,有些人就是不習慣這語法。。 在了解更多選擇如Ocaml、Haskell、Erlang,琢磨了動態語言、函數式語言的編譯後,,對Lisp的認識也比較理性了。。
關於「Lisp邪教」的說法, 「括弧」是一大原因(可是說不習慣括弧的又何曾試著去習慣——寫過多少東西。。),另外@開源哥 提到的「那一票人」也有一定責任,相關都不代表因果,何況相關都算不上吧(大家看到的人是極有限的)。。
總之,通過Lisp可以學到很多東西;用得順手自然好,不喜歡還有很多其他選擇。謝邀。我試試看能不能提供另一個視角:
對於有追求的程序員,遲早會走到「自己捲袖子從頭寫自用的整個軟體世界」這一步。這時,選擇什麼編程語言就是一個很重要的問題:萬一選了一個以後沒人維護的編程語言,有可能寫了幾十年的代碼最後都白寫了(沒法在最新的機器上運行)
但是,如果使用Lisp的話,完全不用擔心這一點。Lisp的規則是如此簡單,以至於任何人可以在任何圖靈完備的計算環境上(無論有多新、多舊、多古怪)迅速寫出一個最基礎的解釋器。對於老手大概只要15分鐘
因此,你永遠不用擔心自己寫的Lisp代碼以後會作廢。你可以很有信心地認為無論身處世界的任何一隅,無論生活在什麼時代,只要15分鐘就能恢復自己的全部編程世界。對於捲袖子的程序員,這就是聖杯
作為對比,重新寫一個JVM或者C編譯器或許是一個很大的工程,以至於絕大多數人沒有精力獨自完成
當然,你會說「最基礎的Lisp解釋器可是超沒效率的」。沒錯,但是如果你眼光放長遠一點,就會發現硬體的進步會很快補償這種低效率。Paul Graham說的「為100年以後設計的語言」大概就是這個意思
【搗亂向】
妮曰:「你們討論的是哪一門lisp?」
只要括弧套括弧就是lisp?還是僅限於Common Lisp?Clojure?Scheme?Racket?還是233-lisp?。。。被拉來回答這個。。。
(我並不「精通」 Lisp 。。。除了大忽悠那一票人之外估計沒人敢說自己精通 Lisp。。。)
寫 Lisp 寫習慣了之後看別的語言都會有種「啊 Lisp 里這樣不就實現了這個 xx 語言的 oo 特性了嗎」這種感覺
而且 Lisp ,或者說函數式的編程風格很優雅,我之前在學校寫作業用 Java 的時候就會不自覺的寫出 Lisp 風格的代碼(然後被教授噴)
啊還有就是寫代碼時候不注重運行效率(寫 Lisp 還考慮什麼效率啊)
還有一點就是上數學課看括弧頭不疼了=,=
http://paulgraham.com/avg.html
(defmacro defn (fname args optional docstring rest body)
"Macro to define a function with improved argument documentation.
FNAME is a symbol for the function name.
ARGS is a list of arguments. Each argument can be either a symbol
or a list of the form (arg-symbol arg-docstring options) where
options is a plist style of options that include:
:default value
:validate function (the function takes one argument, and should
return t if the argument is valid.
:rest (this indicates the rest of the arguments go into this
variable, and it has to be last)
The function docstring is built up from that information.
Default values will automatically be set in the body, and
validation code will be automatically generated if the option is
present.
DOCSTRING is an optional string for the overall purpose of the
function. The argument docstrings will be appended onto this.
BODY is a form for the function."
(if (not (stringp docstring))
(setq body docstring
docstring "No documentation provided."))
(let* (_ds
arg-options
;; build up the docstring.
(ds (concat
(or docstring "No docstring defined.")
"
"
(mapconcat
"identity
(loop for arg in args
collect
(cond
((listp arg)
(setq arg-options (if (stringp (nth 1 arg))
(cddr arg)
(cdr arg)))
(format "%s : %s%s%s"
(upcase (symbol-name (car arg)))
(if (stringp (nth 1 arg)) (nth 1 arg) "No documentation")
(if (plist-get arg-options :default)
(format " (default = %s)"
(plist-get arg-options :default))
"")
(if (plist-get arg-options :validate)
(format " (valid = %s)"
(plist-get arg-options :validate))
"")))
;; this is a standalone symbol
(t
(format "%s : No documentation"
(upcase (symbol-name arg))))))
"
")
"
"))
;; These are the args to go in the function definition
(newargs (loop for arg in args
append
(cond
((listp arg)
(cond
((plist-get (cddr arg) :default)
`(optional ,(car arg)))
((member :rest arg)
`(rest ,(car arg)))
(t
(list (car arg)))))
(t
(list arg)))))
;; This is the code to set default values
(defaults (delq nil
(loop for arg in args
collect
(when (and (listp arg) (plist-get (cddr arg) :default))
`(when (null ,(car arg))
(setq ,(car arg) ,(plist-get (cddr arg) :default)))))))
;; This is the code to validate arguments
(validate (delq nil
(loop for i from 0 for arg in args
collect
(when (and (listp arg) (plist-get
(delq :rest (cddr arg)) :validate))
`(unless (funcall ",(plist-get
(delq :rest (cddr arg))
:validate)
,(car arg))
(error "In (%s %s) Expected %s to pass %S. Got %S"
,(symbol-name fname) ,(format "%s" newargs)
,(symbol-name (car arg))
",(plist-get (delq :rest (cddr arg)) :validate)
,(car arg)))))))
(f `(defun ,fname (,@newargs)
,(or ds "No docstring defined ;(."))))
(when defaults (setq f (append f `((progn ,@defaults)))))
(when validate (setq f (append f `((progn ,@validate)))))
(setq f (append f `,@body))))
來自 jkitchin/scimax
Lisp的括弧看得頭暈,需要一個給力的編輯器。
並非精通,在這裡分享一點體會。
1、面試現在公司的時候,面試官看到我的簡歷的角落裡寫了Lisp,於是讓我寫了一段支持尾遞歸的費波那其數列的Lisp函數(其實他並不熟悉),這是我唯一一次把Lisp用於正式工作;2、我從Lisp里學到了很多現代語言中「被重新發明」的概念。當我閱讀到其他語言的宏(包括C#的Expression)、多分派(如Lobster),我很容易通過Lisp已經教會我的概念去類比;3、這是一個副作用,就是想設計DSL時,不自覺會寫成S表達式,因為parse太方便了。推薦閱讀:
※Lisp 對於編程語言的發展有哪些貢獻?
※在lambda表達式中如何使用遞歸?
※Python 中的 lambda 和「真正的」lambda 有什麼區別?
※Lisp的精髓是什麼?