Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I test whether a variable is defined before referencing it?

Tags:

scheme

I would like to be able to test whether a variable is defined, prior to accessing it.

I like to have a global that specifies a "debug level". If debug level is 0, no extra output is given. When greater than 1, debug output is given, with more verbosity at greater numbers.

I also would like to set it up so that the procedures would run, and assume a level 0, if I had not gotten around to defining it. Something like: (where defined? is the magic I don't know how to do?

(if (and (defined? debug-level) (> debug-level 1))
    (diplay "Some debugging info"))

I have looked through the summary of forms in The Scheme Programming Language, 4th Edition. The only one that I saw as a possibility was identifier?. It did not work.

I'm using SISC 1.16.6 (claims R5RS compliance) and Chez Petite Scheme v8 (claims R6RS compliance)

EDIT I tried wrapping eval with a guard like:

(guard (x (else #f)) (eval 'debug-level))

Since 'debug-level is quoted it can be evaluated and passed to eval. Then when eval tries to evaluate it, an error would happen, which I hoped guard would catch. It didn't.

EDIT 2 I realized that I wanted to wrap the debug tracing into a seperate procedure and that the file that defines that procedure can also define debug-level with a default of 0. The reasons for using a seperate procedure are to lower the number of lines in the procedures that do work and also to allow the redirection of debug output if needed.

like image 817
Shannon Severance Avatar asked Jul 16 '10 17:07

Shannon Severance


People also ask

How do you check if a variable is defined?

The typeof operator will check whether a variable is defined or not. The typeof operator doesn't throw a ReferenceError exception when it is used with an undeclared variable. The typeof null will return an object. So, check for null also.

How do you check if a variable is not defined?

To check if a variable is undefined, you can use comparison operators — the equality operator == or strict equality operator === . If you declare a variable but not assign a value, it will return undefined automatically. Thus, if you try to display the value of such variable, the word "undefined" will be displayed.

How do you test if a variable is defined in Python?

Python doesn't have a specific function to test whether a variable is defined, since all variables are expected to have been defined before use, even if initially assigned the None object.

How do you check if a variable is defined JS?

Use the typeof operator to check if a variable is defined or initialized, e.g. if (typeof a !== 'undefined') {} . If the the typeof operator doesn't return a string of "undefined" , then the variable is defined.


3 Answers

This is totally up to the implementation to provide, and it looks like most implementations don't satisfactorily provide it.

In SISC scheme, it looks like you can use GETPROP to this effect, but environments don't update automatically oh, look, there's this thing called INTERACTION-ENVIRONMENT that you can use:

#;> (getprop 'cons (interaction-environment))
#<native procedure cons>
#;> (getprop 'x (interaction-environment))
#f
#;> (define x 100)
#;> (getprop 'x (interaction-environment))
100

But it only works on the top level.

#;> (define (foo y)
  (let ((e (interaction-environment)))
    (display "Is X bound? ") (display (getprop 'x e))
    (newline)
    (display "Is Y bound? ") (display (getprop 'y e))
    (newline) ))
#;> (foo 1)
#;> Is X bound? 100
Is Y bound? #f

For Chez you have TOP-LEVEL-BOUND? and INTERACTION-ENVIRONMENT again.

like image 82
Nietzche-jou Avatar answered Sep 26 '22 00:09

Nietzche-jou


Clunky but workable solution for R5RS. Use the often neglect/forgotten ability of let-syntax to redefine keywords. this is clunky because your whole file is wrapped in a let-syntax and because it adds some overhead to each define. I use a associative list to remember definitions, a hash table would be a beter choice.

(define define-list '())
(define define-list-add 
  (lambda (key value)
    (set! define-list (cons `(,key ,value) define-list))))

(let-syntax (
             (define (syntax-rules ()
                       ((_ (pro-name args ...) body ...) 
                        (begin
                          (define (pro-name args ...) body ...)
                          (define-list-add pro-name  '((pro-name args ...) body ...))))
                       ((_ pro-name pro) (begin
                                           (define pro-name pro)
                                           (define-list-add 'pro-name 'pro)))

                       ))
             (defined?
               (syntax-rules ()
                 ((_ sym) (begin (if (assoc (quote sym) define-list) #t #f)))))
             )
  (define y (lambda () x))

  (display (defined? y))
  (newline)
  (display (defined? x))
  )

prints

#t
#f

Below in racket: a module is used to redefine define to store each symbol and definition in a list called define-list. The macro defined? looks in this list to see if weather or not the symbol has been defined.

(module qdefine mzscheme
  (provide ;(all-from-except mzscheme let)
   (rename define olddefine)
   (rename quote-define define)
   defined?)

  (define define-list '())
  (define define-list-add 
    (lambda (key value)
      (set! define-list (cons `(,key ,value) define-list))))

  (define-syntax quote-define
    (syntax-rules ()
      ((_ (pro-name args ...) body ...) 
       (begin
         (define (pro-name args ...) body ...)
         (define-list-add pro-name  '((pro-name args ...) body ...))))
      ((_ pro-name pro) (begin
                          (define pro-name pro)
                          (define-list-add 'pro-name 'pro)))

      ))

  (define-syntax defined?
    (syntax-rules ()
      ((_ sym) (begin (if (assoc (quote sym) define-list) #t #f)))))
  )
(require 'qdefine)

(define y (lambda () x))

(defined? y)
(defined? x)

In guile it is just defined? apparently: http://www.delorie.com/gnu/docs/guile/guile_289.html

like image 43
Davorak Avatar answered Sep 25 '22 00:09

Davorak


To back up a bit, the problem with a defined? function is that if you write

(defined? debug-level)

Scheme will attempt to evaluate debug-level, which of course is an error since it is not defined. Such a form would have to be implemented internally by the compiler/interpreter as a special case.

Such a special form is not part of the R5RS standard (unless I missed it, please double-check). So with regard to R5RS schemes you are out of luck unless you find a Scheme that implements this as a non-standard extension.

like image 33
Justin Ethier Avatar answered Sep 26 '22 00:09

Justin Ethier