为什么Lisp允许在let中替换数学运算符?

wan*_*kai 2 lisp scheme clojure

我知道在Scheme中我可以这样写:

(let ((+ *)) (+ 2 3)) => 6
Run Code Online (Sandbox Code Playgroud)

除此之外,在Clojure中:

(let [+ *] (+ 2 3)) => 6
Run Code Online (Sandbox Code Playgroud)

我知道这可以解决问题,但是感觉很奇怪。我认为在任何语言中,数学运算符都是预定义的。C ++和Scala可以执行运算符重载,但是事实并非如此。

这不会引起混乱吗?为什么Lisp允许这样做?

Rai*_*wig 7

这不是Lisp的常规功能。

在Common Lisp中,绑定核心语言功能的效果未定义。这意味着开发人员不应期望它可移植代码中工作。一个实现也可以发出警告或错误的信号。

例如,SBCL编译器将发出此错误信号:

; caught ERROR:
;   Lock on package COMMON-LISP violated when
;   binding + as a local function while
;   in package COMMON-LISP-USER.
;   See also:
;     The SBCL Manual, Node "Package Locks"
;     The ANSI Standard, Section 11.1.2.1.2

;     (DEFUN FOO (X Y)
;       (FLET ((+ (X Y)
;                (* X Y)))
;         (+ X Y)))
Run Code Online (Sandbox Code Playgroud)

我们可以+在Common Lisp中拥有自己的组件,但是必须将它放在另一个包中(=符号名称空间):

(defpackage "MYLISP"
  (:use "CL")
  (:shadow CL:+))

(in-package "MYLISP")

(defun foo (a b)
  (flet ((+ (x y)
           (* x y)))
    (+ a b)))
Run Code Online (Sandbox Code Playgroud)


cfr*_*ick 6

免责声明:这是从Clojure的角度来看。

+只是另一个功能 您可以将其传递并编写sum,具有部分应用程序,请阅读有关它的文档,...:

user=> (apply + [1 2 3])
6
user=> (reduce + [1 2 3])
6
user=> (map (partial + 10) [1 2 3])
(11 12 13)
user=> `+
clojure.core/+
user=> (doc +)
-------------------------
clojure.core/+
([] [x] [x y] [x y & more])
  Returns the sum of nums. (+) returns 0. Does not auto-promote
  longs, will throw on overflow. See also: +'
Run Code Online (Sandbox Code Playgroud)

因此,您可以+在不同的命名空间中有很多。默认情况下,核心一键的“使用”已为您使用,但您可以自己编写。您可以编写自己的DSL:

user=> (defn + [s] (re-pattern (str s "+")))
WARNING: + already refers to: #'clojure.core/+ in namespace: user, being replaced by: #'user/+
#'user/+
user=> (+ "\\d")
#"\d+"
user=> (re-find (+ "\\d") "666")
"666"

Run Code Online (Sandbox Code Playgroud)

它不是特殊形式,与其他任何功能都没有什么不同。因此,在建立了该名称之后,为什么应该允许它被覆盖?