[racket] non-shared module variables

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Tue May 28 08:33:50 EDT 2013

I would personally go with the syntax-parameter approach.

Another option is:

(define-syntax (module-begin stx)
  (syntax-case stx ()
    [(_ . body)
     (with-syntax
         ([add (datum->syntax stx 'add)]
          [get (datum->syntax stx 'get)])
       (syntax/loc stx
         (#%module-begin
          (define state null)
          (define (add v)
            (set! state (cons v state)))

          (define (get)
            state)

          . body)))]))

But that puts add and get into the module, which means they can't use
those names, etc.

I'm not sure what complexity you are worried about with the stxparam
version, but this may help:

#lang racket/base
(require racket/stxparam
         racket/splicing
         (for-syntax racket/base
                     racket/syntax
                     racket/list))

(begin-for-syntax
  (define local-state empty)
  (define local-state-fs empty))

(define-syntax-rule (define-invocation-local-state id init)
  (begin
    (begin-for-syntax
      (set! local-state
            (cons
             #'(id init)
             local-state)))
    (define-syntax-parameter id
      (λ (stx) (raise-syntax-error 'id "Local state" stx)))))

(define-syntax-rule
  (define-invocation-local-state-dependent-function (f . args) . body)
  (begin
    (begin-for-syntax
      (set! local-state-fs
            (cons
             #'(f args body)
             local-state-fs)))
    (define-syntax-parameter f
      (λ (stx) (raise-syntax-error 'f "Local state" stx)))))

(define-syntax (module-begin stx)
  (syntax-case stx ()
    [(_ . body)
     (with-syntax*
         ([((local-state-id local-state-init) ...)
           local-state]
          [((local-f local-f-args local-f-body) ...)
           local-state-fs]
          [(local-f-new-id ...)
           (generate-temporaries #'(local-f ...))])
       (syntax/loc stx
         (#%module-begin
          (define local-state-new-id local-state-init)
          ...
          (splicing-syntax-parameterize
           ([local-state-id (make-rename-transformer #'local-state-new-id)]
            ...)
           (define (local-f-new-id . local-f-args) . local-f-body)
           ...)
          (splicing-syntax-parameterize
           ([local-f (make-rename-transformer #'local-f-new-id)]
            ...)
           (begin . body)))))]))

(define-invocation-local-state state null)
(define-invocation-local-state-dependent-function (add v)
  (set! state (cons v state)))
(define-invocation-local-state-dependent-function (get)
  state)

(provide (except-out (all-from-out racket/base)
                     #%module-begin)
         (rename-out [module-begin #%module-begin])
         add get)


On Tue, May 28, 2013 at 5:59 AM, Tobias Hammer <tobias.hammer at dlr.de> wrote:
> Hi,
>
> i am trying to write a simple language that has variables that should not be
> shared, i.e that should be local to an invocation of the module-language.
>
> Example:
> ;; -------------------------------
> #lang racket
>
> ;; lang
> (module lang racket
>   (provide (all-from-out racket)
>            add get)
>
>   (define state null)
>
>   (define (add v)
>     (set! state (cons v state)))
>
>   (define (get)
>     state))
>
> ;; mods
> (module m (submod ".." lang)
>   (add 'from-m)
>   (get))
>
> (module n (submod ".." lang)
>   (add 'from-n)
>   (get))
>
> (require 'm)
> (require 'n)
> ;; -------------------------------
>
> This gives
> '(from-m)
> '(from-n from-m)
>
> but what i want is
> '(from-m)
> '(from-n)
>
> That means the state-variables should be unique to n and m. The allowed
> functions inside the modules should at best be all from 'module context, but
> at least require and provide should be possible.
>
> I tried overwriting #%module-begin and wrap the module body in parameterize,
> but this limits to expression-context. syntax-parameters with
> splicing-syntax-parameterize didn't work without converting everything in
> lang to macros which would add a lot of complexity.
>
> So, the question is, what is the right way to get the desired behavior?
>
> Tobias
>
>
>
> --
> ---------------------------------------------------------
> Tobias Hammer
> DLR / Robotics and Mechatronics Center (RMC)
> Muenchner Str. 20, D-82234 Wessling
> Tel.: 08153/28-1487
> Mail: tobias.hammer at dlr.de
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users



-- 
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93


Posted on the users mailing list.