macrosschemelispcommon-lisplisp-macros

What is standard way of defining global closures in scheme?


So I want to know if there is standard way of having code like this:

(let ((x 10))
  (define (add10 a)
     (+ x a)))

I know about:

(define add10 (let ((x 10))
                 (lambda (a) (+ x a))))

but this will not work if I want to define multiple functions, I need to know standard way so I can write macro that will define functions. where you can call macro inside let:

(let ((x 10))
  (macro x))

and for instance macro will create list of functions:

(let ((x 10))
  (define (add1)
     (+ x 1))
  (define (add2)
     (+ x 2))
  (define (add3)
     (+ x 3)))

Is there standard way of defining functions add1..add3? In scheme I was testing, the functions will be local inside let and not accessible outside.

If you show macro code I'm only interested in lisp macros with define-macro and quasiquote, please no define-syntax, because this is mostly for use in my own lisp (based on scheme) where I have only lisp macros.

If scheme don't give support for something like that, does other dialect like Common Lisp allow something like this?


Solution

  • (let ((x 10))
      (somemacro x))
    

    ->

    (let ((x 10))
      (define (add1)
         (+ x 1))
      (define (add2)
         (+ x 2))
      (define (add3)
         (+ x 3)))
    

    In Common Lisp:

    CL-USER 43 > (defmacro somemacro (var)
                   `(progn
                      (defun add1 () (+ ,var 1))
                      (defun add2 () (+ ,var 2))
                      (defun add3 () (+ ,var 3))))
    SOMEMACRO
    
    CL-USER 44 > (let ((x 10))
                   (somemacro x))
    ADD3
    
    CL-USER 45 > (add1)
    11
    
    CL-USER 46 > (add3)
    13
    

    One sees that sometime. Generally exactly this is slight bad style in Common Lisp, because the file compiler will then not recognize that there are global function declarations, because inside the LET a DEFUN is not at top-level. If a function is defined in a file at top-level, then at compile time the file compiler would see that this is a function and may do special things like noting the signature in the compile-time environment, inlining it. etc.

    Note that when DEFINE in Scheme defines a local function, one still might be able to do (depending on what the implementation does additionally to the standard):

    (let ((x 10))
      ()
      (define (add1) (+ x 1)))
    

    Note that in Common Lisp defun defines global functions and flet / labels define local functions.