为什么不赞成使用SET?

时间:2014-03-02 20:25:16

标签: common-lisp deprecated

我很想知道这个原因,因为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,这是可笑的。感谢。

2 个答案:

答案 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那样应该避免它,并且只作为最后的手段使用。