[racket] Redefinition of initial bindings/ Resessive genes in GP

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Sun Jul 8 14:30:13 EDT 2012

2012/7/8  <jukka.tuominen at finndesign.fi>:
>
> I came across this "mutable-define" by Eli (3+ years back)...
>
> ;; http://paste.lisp.org/display/67203
> ;; this is a PLT version, translate as necessary
>
> (define-syntax-rule (define-mutable name expr)
>   (begin (define b (box expr))
>          (define-syntax name
>            (syntax-id-rules (set!)
>              [(set! name new) (set-box! b new)]
>              [(name . xs) ((unbox b) . xs)]
>              [name (unbox b)]))))
>
> ;(define x 1)
> ;(define x 2)
>
>
> ...which seems beautifully concise for the job. The only problem is that
> it only seems to work in the interactions window in drracket. Is there a
> way to have it working inside a module? ... hopefully so that all the
> tweaks would take place inside the very module, rather than "required"
> from elsewhere (that would keep it an GP individual's property/"gene").
>
> This is obviously what Danny is trying to explain me - "...language
> variant of Racket where "define" acts like redefinition at the module
> toplevel..." - but once again, I seem to be reaching out things before
> understanding them.

Combining Dannys def and Eli's define-mutable I get this:


#lang racket

;; Returns true if stx is an identifier that's been lexically bound.
(define-for-syntax (lexically-bound? stx)
  (let ([expanded (local-expand stx (syntax-local-context) #f)])
    (not (and (identifier? expanded)
              (eq? #f (identifier-binding expanded))))))

(define-syntax (defm stx)
  (syntax-case stx ()
    [(_ name expr)
     (and (identifier? #'name) (lexically-bound? #'name))
     (syntax/loc stx (set! name expr))]
    [(_ name expr)
     (identifier? #'name)
     (syntax/loc stx
       (begin
         (define b (box expr))
         (define-syntax name
           (make-set!-transformer
            (lambda (stx)
              (syntax-case stx (set!)
                [(set! name new) #'(set-box! b new)]
                [(name . xs)     #'((unbox b) . xs)]
                [name            #'(unbox b)]))))))]))

;;; Testing

(defm x 1)
x
(list (+ x 40))
(defm x 2)
x
(list (+ x 40))
(set! x 3)
x


(defm y 4)
y
(list (+ y 40))
(defm y 5)
y
(list (+ y 40))
(set! y 6)
y


; The output is

1
'(41)
2
'(42)
3
4
'(44)
5
'(45)
6


-- 
Jens Axel Søgaard


Posted on the users mailing list.