Я хотел бы смочь протестировать, определяется ли переменная до доступа к нему.
Мне нравится иметь глобальное, которое указывает "уровень отладки". Если уровень отладки 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. Причины использования отдельной процедуры состоят в том, чтобы понизить количество строк в процедурах, которые действительно работают и также позволить перенаправление вывода отладки в случае необходимости.
Это полностью зависит от реализации, и похоже, что большинство реализаций не обеспечивают это удовлетворительно.
В схеме 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.
Неуклюжее, но работоспособное решение для 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
Чтобы немного отступить назад, проблема с defined?
функцией заключается в том, что если вы напишите
(defined? debug-level)
Scheme попытается оценить debug-level
, что, конечно, является ошибкой, поскольку она не определена. Такая форма должна быть реализована внутри компилятора/интерпретатора как специальный случай.
Такая специальная форма не является частью стандарта R5RS (если я не пропустил, пожалуйста, перепроверьте). Так что в отношении схем R5RS вам не повезло, если только вы не найдете схему, которая реализует это как нестандартное расширение.