
@sorawee Your recent experiments with definitions in an expression context made be think of a similar problem.
I’d like to have an definition/assignment form (:= id expr)
that works like define
the first time :=
is used with an identifier and like set!
the second, third, etc. time. Simply expanding :=
to define doesn’t work, due to duplicate definitions of the same identifier. There is module wide setting to turn that restriction off, but I’d like to keep the restriction for standard define
.
If :=
also works in an expression context, that would just be a bonus.


Your if-defined
makes it simple: #lang racket
; The macro
(define-syntax (if-defined stx)
(syntax-case stx ()
[(_ id iftrue iffalse)
(let ([where (identifier-binding #'id)])
(if where #'iftrue #'iffalse))]))
; Tests
(if-defined z (list z) 'not-defined) ; -> not-defined
(if-defined t (void) (define t 5))
t ; -> 5
(define x 3)
(if-defined x (void) (define x 6))
x ; -> 3
(define-syntax (:= stx)
(syntax-case stx ()
[(_:= id expr)
(syntax/loc stx
(if-defined id
(set! id expr)
(define id expr)))]))
(:= a 42)
a
(:= a 43)
a