Search code examples
moduleschemeread-eval-print-looplexical-scopeguile

difference between let inside and outside a lambda expression


Consider a module with the following procedures:

(define-module (test test)
  #:export     (proc1 proc2 proc3))

(define proc1
  (let ((module (current-module)))
    (lambda ()
      (format #t "~s\n" module))))

(define proc2
  (lambda ()
    (let ((module (current-module)))
      (format #t "~s\n" module))))

(define (proc3)
  (let ((module (current-module)))
    (format #t "~s\n" module)))

I was under the impression that all these were equivalent, but they are not.

scheme@(guile-user)> (use-modules (test test))
scheme@(guile-user)> (proc1)
#<directory (test test) 562a062152d0>
$1 = #t
scheme@(guile-user)> (proc2)
#<directory (guile-user) 562a05b8bbd0>
$2 = #t
scheme@(guile-user)> (proc3)
#<directory (guile-user) 562a05b8bbd0>
$3 = #t

Only in proc1 the module symbol inside the lambda expression is bound to the module were the procedure is defined.

Can somebody explain this? Does it mean I always have to use the first form, if I want to create a closure?


Solution

  • proc1 evaluates (current-module) only once, when the procedure is defined, so module inside the lambda is bound to that value at definition-time.

    proc2 does not evaluate (current-module) until the procedure is called.
    It also evaluates it every time.
    It is equivalent to proc3.