Как я тестирую, определяется ли переменная прежде, чем сослаться на него?

Я хотел бы смочь протестировать, определяется ли переменная до доступа к нему.

Мне нравится иметь глобальное, которое указывает "уровень отладки". Если уровень отладки 0, никакой дополнительный вывод не дан. Когда больше, чем 1, вывод отладки дан с большим количеством многословия в больших числах.

Я также хотел бы настроить его так, чтобы процедуры работали и предположили уровень 0, если я не нашел время для определения его. Что-то как: (где defined? волшебство, я не знаю, как сделать?

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

Я просмотрел сводку форм на Языке программирования Схемы, 4-м Выпуске. Единственный, который я рассматривал как возможность, был identifier?. Это не работало.

Я использую SISC 1.16.6 (утверждает, что соответствие R5RS) и Миниатюрная Схема v8 Chez (требует соответствия R6RS),

ОТРЕДАКТИРУЙТЕ я пытался перенестись eval с a guard как:

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

С тех пор 'debug-level заключается в кавычки это может быть оценено и передано eval. Затем, когда eval попытки оценить его, ошибка произошла бы, который я надеялся guard поймал бы. Это не сделало.

ОТРЕДАКТИРУЙТЕ 2, я понял, что хотел перенести трассировку отладки в отдельную процедуру и что файл, который определяет ту процедуру, может также определить debug-level со значением по умолчанию 0. Причины использования отдельной процедуры состоят в том, чтобы понизить количество строк в процедурах, которые действительно работают и также позволить перенаправление вывода отладки в случае необходимости.

6
задан Shannon Severance 19 July 2010 в 15:45
поделиться

3 ответа

Это полностью зависит от реализации, и похоже, что большинство реализаций не обеспечивают это удовлетворительно.

В схеме SISC, похоже, вы можете использовать GETPROP для этого, но окружения не обновляются автоматически О, смотрите, есть такая штука, называемая INTERACTION-ENVIRONMENT, которую вы можете использовать:

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

Но она работает только на верхнем уровне.

#;> (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

Для Chez у вас есть TOP-LEVEL-BOUND? и снова INTERACTION-ENVIRONMENT.

4
ответ дан 17 December 2019 в 00:02
поделиться

Неуклюжее, но работоспособное решение для R5RS. Используйте часто игнорируемую/забытую возможность let-syntax для переопределения ключевых слов. Это неудобно, потому что весь ваш файл обернут в let-syntax и потому что это добавляет некоторые накладные расходы на каждое определение. Я использую ассоциативный список для запоминания определений, хэш-таблица была бы лучшим выбором.

(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

Ниже в racket: модуль используется для переопределения define, чтобы хранить каждый символ и определение в списке, называемом define-list. Макрос 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)

В guile это просто defined? очевидно: http://www.delorie.com/gnu/docs/guile/guile_289.html

2
ответ дан 17 December 2019 в 00:02
поделиться

Чтобы немного отступить назад, проблема с defined? функцией заключается в том, что если вы напишите

(defined? debug-level)

Scheme попытается оценить debug-level, что, конечно, является ошибкой, поскольку она не определена. Такая форма должна быть реализована внутри компилятора/интерпретатора как специальный случай.

Такая специальная форма не является частью стандарта R5RS (если я не пропустил, пожалуйста, перепроверьте). Так что в отношении схем R5RS вам не повезло, если только вы не найдете схему, которая реализует это как нестандартное расширение.

1
ответ дан 17 December 2019 в 00:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: