Matt Wette schreef op zo 19-09-2021 om 07:45 [-0700]: > On 9/19/21 3:38 AM, Maxime Devos wrote: > > [...] > > (use-modules (system syntax)) > > (define-syntax define-or-set! > > (lambda (s) > > (syntax-case s () > > ((_ var value) > > (case (syntax-local-binding #'var) > > ((lexical displaced-lexical) #'(set! var value)) > > ((global) #'(define var value)) > > (else ???)))))) > > > > ,expand (define-or-set! a 0) ; $_ = (define a 0) > > ,expand (let ((a 0)) (define-or-set! a 0) a) ; $_ = (let ((a 0)) (set! a 0) a) > > (define-or-set! a 0) > > ,expand (define-or-set! a 0) ; $_ = (define a 0) (might or might not be acceptable for your use case > > ,expand (let () (define-or-set! a 0) (define-or-set! a 1) a) ; $_ = (let () (define a 0) (set! a 1)) > > > > Greetings, > > Maxime. > > Does this work for you? > > scheme@(guile-user)> (define a 1) > scheme@(guile-user)> (define a 2) > scheme@(guile-user)> a > $2 = 2 > scheme@(guile-user)> If I use 'define', the following evaluates to zero: (define a 0) (let () (define a 1) (values)) a (the inner 'a' shadows the global 'a', thus the last a evaluates to 0 instead of 1) However, Damien Mattei asked for a variant of 'define' that only defines a variable if it is not yet bound (let's call this variant define-or-set!) (define-or-set! a 0) (let () (define-or-set! a 1) (values)) a As within the 'let' expression, 'a' is already bound (to the global variable), due to the first (define-or-set! a 0), the inner 'define-or-set!' should set! 'a' instead of defining a new variable 'a'. As such, the code above should expand to: (define a 0) (let () (set! a 1) (values)) a ; evaluates to 1. Possibly Damien Mattei wants something else though ...