how to know if a variable is defined

Damien Mattei damien.mattei@gmail.com
Tue Apr 16 06:37:48 GMT 2024


this could not works because the defined-symbol? used in the macro
if-defined return false because at the expansion of the macro the symbol is
not defined.

Instead at run-time, this works:

#|kawa:21|# (define (foo2) (define x 7) (defined-symbol? x))
#|kawa:22|# (foo2)
#t

On Sun, Apr 14, 2024 at 12:58 AM Damien Mattei <damien.mattei@gmail.com>
wrote:

> just a few add, it has nothing to see with module,the same behavior
> happens at REPL and toplevel:
>
> #|kawa:1|# (define-syntax defined-symbol?
> #|.....2|#   (syntax-rules ()
> #|.....3|#     ((_ x) (call-with-current-continuation
> #|.....4|#    (lambda (exit)
> #|.....5|#      (with-exception-handler
> #|.....6|#       (lambda (e)
> #|.....7|# (display "defined-symbol? : undefined") (newline)
> #|.....8|# (exit #f)) ; eval failed => not defined
> #|.....9|#       (lambda ()
> #|....10|# (eval x (interaction-environment))
> #|....11|# #t))))))) ; eval suceeded => defined
> #|kawa:12|# (define-syntax if-defined
> #|.....13|#   (lambda (stx)
> #|.....14|#     (syntax-case stx ()
> #|.....15|#       ((_ id iftrue iffalse)
> #|.....16|#        (let ((where (defined-symbol? #'id))) ;;(quote id))))
> #|.....17|# (display "if-defined : where=") (display where) (newline)
> #|.....18|# (display "id=") (display #'id) (newline)
> #|.....19|# (if where #'iftrue #'iffalse))))))
> #|kawa:20|# (define-syntax <-
> #|.....21|#    (lambda (stx)
> #|.....22|#
> #|.....23|#      (syntax-case stx ()
> #|.....24|#
> #|.....25|#        ((_ var expr)
> #|.....26|#
> #|.....27|#         #`(if-defined var
> #|.....28|#      (set! var expr)
> #|.....29|#      (define var expr))))))
> #|kawa:30|# (define (foo)
> #|.....31|#   (define expr2 '())
> #|.....32|#
> #|.....33|#   (<- expr2 7))
> defined-symbol? : undefined
> if-defined : where=#f
> id=expr2
> /dev/tty:33:7: duplicate declaration of 'expr2'
> /dev/tty:31:11: (this is the previous declaration of 'expr2')
>
>
> On Sun, Apr 14, 2024 at 12:45 AM Damien Mattei <damien.mattei@gmail.com>
> wrote:
>
>> hello,
>>
>> i ported my code from guile that use ,as you say it 'exceptions':
>>
>> ;; #|kawa:57|#
>> ;; #|kawa:58|# (define r 2)
>> ;; #|kawa:59|# (if-defined r 'defined (define r 7))
>> ;;if-defined : where=#t
>> ;; id=r
>> ;; (if-defined r 'defined (define r 7))
>> ;; defined
>> ;; #|kawa:60|# r
>> ;; 2
>> ;; #|kawa:61|# (defined-symbol? r)
>> ;; #t
>> ;; #|kawa:62|# (defined-symbol? t)
>> ;; /dev/tty:62:18: warning - no declaration seen for t
>> ;; defined-symbol? : undefined
>> ;; #f
>> ;; #|kawa:63|# (let ((k 7)) (defined-symbol? k))
>> ;; #t
>> ;;
>>
>> (define-syntax defined-symbol?
>>   (syntax-rules ()
>>     ((_ x) (call-with-current-continuation
>>    (lambda (exit)
>>      (with-exception-handler
>>       (lambda (e)
>> (display "defined-symbol? : undefined") (newline)
>> (exit #f)) ; eval failed => not defined
>>       (lambda ()
>> (eval x (interaction-environment))
>> #t))))))) ; eval suceeded => defined
>>
>>
>> ;; #|kawa:86|# (define k 0)
>> ;; #|kawa:87|# (let loop () (if (< k 4) (let () (display k) (newline) (<-
>> k (+ k 1)) (loop))))
>> ;; if-defined : where=#t
>> ;; id=k
>> ;; 0
>> ;; 1
>> ;; 2
>> ;; 3
>> ;; #|kawa:88|# (let () (define k 0) (let loop () (if (< k 4) (let ()
>> (display k) (newline) (<- k (+ k 1)) (loop)))))
>> ;; if-defined : where=#t
>> ;; id=k
>> ;; 0
>> ;; 1
>> ;; 2
>> ;; 3
>> ;; #|kawa:89|# (let () (define s 0) (let loop () (if (< s 4) (let ()
>> (display s) (newline) (<- s (+ s 1)) (loop)))))
>> ;; if-defined : where=#t
>> ;; id=s
>> ;; 0
>> ;; 1
>> ;; 2
>> ;; 3
>> ;; #|kawa:90|# (let ((s 0)) (let loop () (if (< s 4) (let () (display s)
>> (newline) (<- s (+ s 1)) (loop)))))
>> ;; if-defined : where=#t
>> ;; id=s
>> ;; 0
>> ;; 1
>> ;; 2
>> ;; 3
>>
>> (define-syntax if-defined
>>   (lambda (stx)
>>     (syntax-case stx ()
>>       ((_ id iftrue iffalse)
>>        (let ((where (defined-symbol? #'id))) ;;(quote id))))
>> (display "if-defined : where=") (display where) (newline)
>> (display "id=") (display #'id) (newline)
>> (if where #'iftrue #'iffalse))))))
>>
>> i use the code in conjunction with this macro:
>> (define-syntax <-
>>    (lambda (stx)
>>
>>    (syntax-case stx ()
>>
>>         #`(if-defined var
>>      (set! var expr)
>>     (define var expr))))))
>>
>> it works better than guile (guile fails on the let () tests...:
>> scheme@(guile-user)> (let ((k 0)) (let loop () (if (< k 4) (let ()
>> (display k) (newline) (<- k (+ k 1)) (loop)))))
>> defined-symbol? : undefined
>> if-defined : where=#f
>> id=#<syntax:unknown file:19:72 k>
>> #<unspecified>
>> ice-9/boot-9.scm:1685:16: In procedure raise-exception:
>> In procedure +: Wrong type argument in position 1: #<unspecified>
>>
>> Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
>>
>> ), as you can see the examples , but in some place of my code kawa fails
>> too, i made a simplified example from the whole code:
>>
>> for example if i put all the stuff in a module test-defined.scm:
>>
>> (module-name test-defined)
>>
>> (export foo)
>>
>>
>>
>> (define-syntax defined-symbol?
>>   (syntax-rules ()
>>     ((_ x) (call-with-current-continuation
>>    (lambda (exit)
>>      (with-exception-handler
>>       (lambda (e)
>> (display "defined-symbol? : undefined") (newline)
>> (exit #f)) ; eval failed => not defined
>>       (lambda ()
>> (eval x (interaction-environment))
>> #t))))))) ; eval suceeded => defined
>>
>> (define-syntax if-defined
>>   (lambda (stx)
>>     (syntax-case stx ()
>>       ((_ id iftrue iffalse)
>>        (let ((where (defined-symbol? #'id))) ;;(quote id))))
>> (display "if-defined : where=") (display where) (newline)
>> (display "id=") (display #'id) (newline)
>> (if where #'iftrue #'iffalse))))))
>>
>>
>>
>> (define-syntax <-
>>    (lambda (stx)
>>
>>      (syntax-case stx ()
>>
>>        ((_ var expr)
>>
>>         #`(if-defined var
>>      (set! var expr)
>>      (define var expr))))))
>>
>>
>>
>>
>> (define (foo)
>>   (define expr2 '())
>>
>>   (<- expr2 7))
>>
>> then it fails:
>>
>> #|kawa:1|# (require test-defined)defined-symbol? : undefined
>> if-defined : where=#f
>> id=expr2
>> (require test-defined)
>> /Users/mattei/Scheme-PLUS-for-Kawa/test-defined.scm:95:7: duplicate
>> declaration of 'expr2'
>> /Users/mattei/Scheme-PLUS-for-Kawa/test-defined.scm:93:11: (this is the
>> previous declaration of 'expr2')
>>
>> it finds that expr2 is not defined,then expand a (define expr2 ...) but
>> then cause an error of duplicate declaration of expr2
>>
>>
>> On Thu, Apr 11, 2024 at 3:01 AM Per Bothner <per@bothner.com> wrote:
>>
>>>
>>>
>>> On 4/10/24 14:49, Damien Mattei via Kawa wrote:
>>> > hello,
>>> >
>>> > is there a way to know if a variable is defined in Kawa?
>>> >
>>> > (like 'identifier-binding' in Racket)
>>>
>>> If you need to know if a variable is bound in the dynamic environment,
>>> you could perhaps use eval wrapped in an exception handler.
>>>
>>> There are probably better ways, but I don't remember off-hand.
>>>
>>> Can't think of anything to use if you need information about lexical
>>> bindings.
>>> I supposed you could implemented identifier-binding or something similar.
>>>
>>> --
>>>         --Per Bothner
>>> per@bothner.com   http://per.bothner.com/
>>>
>>


More information about the Kawa mailing list