我很想知道这个原因,因为set
似乎很独特。例如:
(set 'nm 3) ;; set evaluates its first argument, a symbol, has to be quoted
nm ;; ==> evaluates to 3
(set 'nm 'nn) ;; assigns nn to the value cell of nm
nm ;; ==> evaluates to nn
nn ;; ==> ERROR. no value
(set nm 3) ;; since nm evaluates to nn ...
nm ;; evaluates to nn
nn ;; evaluates to 3
为了达到类似的行为,我只能使用setf
:
(setq tu 'ty) ;;
(symbol-value 'tu) ;; returns ty
(setq (symbol-value 'tu) 5) ;; ERROR. setq expects a symbol
(setf (symbol-value tu) 5) ;; has to be unquoted to access the value cell
tu ;; ==> evaluates to ty
ty ;; ==> evaluates to 3
在其他编程语言中,降级的原因非常明确:低效,容易出错或不安全。我想知道当时set
的弃用标准是什么。我所能从网上收集的只是this,这是可笑的。感谢。
答案 0 :(得分:2)
不推荐使用set
的主要原因是它在绑定变量上使用时会导致错误(例如,在函数中):
(set 'a 10)
==> 10
a
==> 10
(let ((a 1)) ; new lexical binding
(set 'a 15) ; modification of the value slot of the global symbol, not the lexical variable
a) ; access the lexical variable
==> 1 ; nope, not 15!
a
==> 15
set
是Lisp是“符号和列表的语言”时代的遗留函数。从那时起,Lisp已经成熟;对符号广告位的直接操作相对较少,并且没有理由使用set
代替更明确的(setf symbol-value)
。
答案 1 :(得分:0)
在你的例子中:
(set nm 'nn) ;; assigns nn to the value cell of nm
nm ;; ==> evaluates to nn
这是完全错误的,也是它被弃用的主要原因。这是评估绑定到nm
的{{1}}时获得的符号。不幸的是,在您的示例中,数字为nn
并且它将在运行时发出错误信号,因为您不能将数字用作变量。如果您要编写3
,则可以在编译时看到错误。
使用(setq 3 'nn)
还有另外一个原因。当您不知道要绑定哪个符号并且编译器无法对其进行优化时,编译非常困难。
set
在其第一个版本中没有自动引用,并且它们甚至没有像Scheme
这样的引用宏。相反,它表示setq
就足够了。很明显,由于Scheme不再有set'
而只有set
,所以它没有。
我个人不同意它应该删除(弃用最终会导致删除)但是像define
那样应该避免它,并且只作为最后的手段使用。