如何确定Chicken Scheme中是否存在变量?

时间:2016-08-09 06:53:17

标签: scheme chicken-scheme

Chicken Scheme中是否有办法在运行时确定当前是否定义了变量?

(let ((var 1))
 (print (is-defined? var))   ; #t

(print (is-defined? var))    ; #f

编辑:XY问题。

我正在编写一个生成代码的宏。这个生成的代码必须在相互递归中调用宏 - 让宏只是调用它自己将无法工作。当递归调用宏时,我需要它的行为与最初调用时的行为不同。我会使用嵌套函数,但是......它是一个宏。

粗略的例子:

(defmacro m (nested)
 (if nested
  BACKQUOTE(print "is nested")
  BACKQUOTE(m #t)

(是的,我知道方案不使用defmacro,但是我来自Common Lisp。而且我似乎无法将反引号放在这里而不会一切都下地狱。)

我不希望宏的INITIAL调用采用额外的参数,只有在递归调用时才有意义。我希望通过其他方式了解它。

我可以获取生成的代码来调用嵌套在第一个宏中并且在调用站点中不存在的宏吗?例如,生成调用(,other-macro)而不是(macro)的代码?

但这应该不起作用,因为宏不是像函数一样的第一类对象......

2 个答案:

答案 0 :(得分:1)

当您编写递归宏时,我会觉得您有一个宏展开(m a b ...)变成(m-helper a (b ...)),可能变成(let (a ...) (m b ...))。这是直接递归,因为您将代码转换为恰好包含宏的代码。

使用destructuring-bind,您实际上只需要跟踪两个变量。一个用于car,一个用于cdr,并且使用隐式重命名宏,不会从表单中重新命名的内容被重命名为hygenic:

(define-syntax destructuring-bind
  (ir-macro-transformer
   (lambda (form inject compare?)
     (define (parse-structure structure expression optional? body)
       ;;actual magic happens here. Returns list structure with a mix of parts from structure as well as introduced variables and globals
       )

     (match form
       [(structure expression) . body ]
       `(let ((tmp ,expression))
          ,(parse-structure structure 'tmp #f body))))))

要检查输入中的某些内容是否与您使用提供的compare?过程相同的符号。例如。 (compare? expression '&optional)

答案 1 :(得分:0)

一般来说,没有办法做到这一点,因为Scheme是词法范围的。如果引用未定义的变量是错误,则询问是否定义了变量没有多大意义。

对于顶层/全局变量,您可以使用symbol-utils egg,但它可能无法正常工作,因为模块中的全局变量也被重写为其他变量。

也许如果你可以说出你 想要做什么,我可以帮助你提供替代解决方案。