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.mccar...@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.ham...@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.ham...@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.ham...@dlr.de

____________________
 Racket Users list:
 http://lists.racket-lang.org/users

Reply via email to