为什么 (e)lisp/clojure 的 defun/defvar/defn 会返回一个 symbol?有什么用?

(e)lisp/clojure 里的 defun/defvar/def 都将函数名称对应的 symbol 作为“返回值”

(setq funname (defun identity (x) x)) ;; funname => 'identity
(setq funname2 (defvar x 1))
(type-of funname) ;; => symbol
(type-of funname2)
(defvar what (defun nice (x) x))
(type-of what) ;; => symbol
(def x (defn nice []))
;; x => #'user/nice

而 scheme/racket 里面,rnrs 说在 toplevel 里面的 (define 约等于 set!。如果像上面代码那样试图获取 (define 的值,大部分的 scheme 都是直接返回 #<void> 或者报错。

常规的语言 py/java 之类的,def 是特殊的结构,并不能取值。

ocaml/haskell 并不能对 let 进行 let。

另一个和 lisp 一样在函数定义时候会把函数名称当作返回值的是 ruby。

x = def nice() end
# x => :nice
x.class # => Symbol

(e)lisp/clojure/ruby 这样做有什么意义或者原因呢?通过这个特性能做什么有意思的事情吗?或者这是由于语言的其它原因,“自然而然”地导致 defun/defvar/def 会返回函数名称?

表达式可以出现在任意位置,所有表达式都要有返回值。用 multiple return value 返回 0 个值才是后来的做法。Emacs lisp 这么做是因为历史遗留。Clojure 因为 JavaScript 也有所有表达式都有返回值的特性干脆照做。别的都没有历史遗留原因的就改了,尤其是没有 symbol 概念的语言。

4 个赞

有道理,scheme 的 define 的确没有办法放在任意地方。