代码之家  ›  专栏  ›  技术社区  ›  johnc

lisp,赋值函数的差异

  •  4
  • johnc  · 技术社区  · 14 年前

    我对lisp还不太熟悉,所以很抱歉问这么简单的问题,

    虽然我理解DEFVAR和DEFPARAMETER之间的区别(DEFVAR只设置未定义的变量),LET只用于局部作用域,但是SETF相对于前面提到的其他赋值函数的用途是什么?

    2 回复  |  直到 9 年前
        1
  •  5
  •   Rainer Joswig mmmmmm    14 年前

    SETF和SETQ设置变量(全局或局部、特殊或词法),但不定义它们。

    编辑:

    Paul说在CLISP SETF中定义了变量。它不是这样的。我们来看看:

    我们有以下计划:

    (defun foo (a)
      (setf baz (* a a))
      a)
    
    (defun bar (a)
      (setf baz (* a a))
      a)
    

    [1]> (compile-file "/tmp/test.lisp")
    ;; Compiling file /tmp/test.lisp ...
    WARNING in FOO in lines 2..4 :
    BAZ is neither declared nor bound,
    it will be treated as if it were declared SPECIAL.
    WARNING in BAR in lines 6..8 :
    BAZ is neither declared nor bound,
    it will be treated as if it were declared SPECIAL.
    ;; Wrote file /tmp/test.fas
    0 errors, 2 warnings
    

    在这两个函数中,CLISP都警告我们变量BAZ既没有声明也没有绑定。CLISP没有拒绝代码,而是将变量BAZ视为特殊变量。

    [1]> (load "/tmp/test")
    ;; Loading file /tmp/test.fas ...
    ;; Loaded file /tmp/test.fas
    T
    [2]> (foo 2)
    2
    [3]> (bar 3)
    3
    [4]> baz
    9
    [5]> (compile-file "/tmp/test.lisp")
    ;; Compiling file /tmp/test.lisp ...
    WARNING in FOO in lines 2..4 :
    BAZ is neither declared nor bound,
    it will be treated as if it were declared SPECIAL.
    WARNING in BAR in lines 6..8 :
    BAZ is neither declared nor bound,
    it will be treated as if it were declared SPECIAL.
    

    不,即使在执行SETF语句之后,CLISP也认为变量BAZ没有被声明。

    ; in: DEFUN BAR
    ;     (SETF BAZ (* A A))
    ; ==>
    ;   (SETQ BAZ (* A A))
    ;
    ; caught WARNING:
    ;   undefined variable: BAZ
    
    ; in: DEFUN FOO
    ;     (SETF BAZ (* A A))
    ; ==>
    ;   (SETQ BAZ (* A A))
    ;
    ; caught WARNING:
    ;   undefined variable: BAZ
    

    LispWorks编译器有这样一句话:

    ;;;*** Warning in FOO: BAZ assumed special in SETQ
    ; FOO
    ;;;*** Warning in BAR: BAZ assumed special in SETQ
    ; BAR
    
        2
  •  3
  •   Doug Currie    14 年前

    SETF 影响现有的绑定或“位置”。您可以使用它来更改用其创建的任何对象的值 LET DEF...

    在Common Lisp中, setf 是“影响宏的广义位置”。参见 CLHS 5.1.1 - Overview of Places and Generalized Reference