Sod Almighty
Sod Almighty

Reputation: 1786

How to determine if a variable exists in Chicken Scheme?

Is there a way in Chicken Scheme to determine at run-time if a variable is currently defined?

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

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

EDIT: XY problem.

I'm writing a macro that generates code. This generated code must call the macro in mutual recursion - having the macro simply call itself won't work. When the macro is recursively called, I need it to behave differently than when it is called initially. I would use a nested function, but uh....it's a macro.

Rough example:

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

(yes, I know scheme doesn't use defmacro, but I'm coming from Common Lisp. Also I can't seem to put backquotes in here without it all going to hell.)

I don't want the INITIAL call of the macro to take an extra argument that only has meaning when called recursively. I want it to know by some other means.

Can I get the generated code to call a macro that is nested within the first macro and doesn't exist at the call site, maybe? For example, generating code that calls (,other-macro) instead of (macro)?

But that shouldn't work, because a macro isn't a first-class object like a function is...

Upvotes: 0

Views: 446

Answers (2)

Sylwester
Sylwester

Reputation: 48765

When you write recursive macros I get the impression that you have an macro expansion (m a b ...) that turns into a (m-helper a (b ...)) that might turn into (let (a ...) (m b ...)). That is not directly recursive since you are turning code into code that just happens to contain a macro.

With destructuring-bind you really only need to keep track of two variables. One for car and one for cdr and with an implicit renaming macro the stuff not coming from the form is renamed and thus 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))))))

To check if something from input is the same symbol you use the supplied compare? procedure. eg. (compare? expression '&optional).

Upvotes: 1

sjamaan
sjamaan

Reputation: 2292

There's no way to do that in general, because Scheme is lexically scoped. It doesn't make much sense to ask if a variable is defined if an referencing an undefined variable is an error.

For toplevel/global variables, you can use the symbol-utils egg but it is probably not going to work as you expect, considering that global variables inside modules are also rewritten to be something else.

Perhaps if you can say what you're really trying to do, I can help you with an alternate solution.

Upvotes: 0

Related Questions