[racket] non-shared module variables

From: Tobias Hammer (tobias.hammer at dlr.de)
Date: Tue May 28 09:54:26 EDT 2013

I thought that the syntax-parameter approach with macros would add  
complexity to functions with optional and/or keyword arguments. But your  
solution with parameterizing over the state and then the functions solves  
my problem completely.

Thanks for sharing this excellent solution!


On Tue, 28 May 2013 14:33:50 +0200, Jay McCarthy <jay.mccarthy at gmail.com>  
wrote:

> 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
>
>
>


-- 
---------------------------------------------------------
Tobias Hammer
DLR / Robotics and Mechatronics Center (RMC)
Muenchner Str. 20, D-82234 Wessling
Tel.: 08153/28-1487
Mail: tobias.hammer at dlr.de


Posted on the users mailing list.