Creating lexically scoped functions in newLISP

A default function looks and behaves similar to statically scoped functions found in other programming languages. Several functions can share one namespace.

Using the built-in primitive def-new, a function or macro can be defined to create other functions enclosed in their own namespace:

  (define (def-static s body) 
      (def-new 'body (sym s s))) 

  (setq sum 0)

  (def-static 'acc (lambda (x)
          (inc sum x)))


  (acc 5)  → 5
  (acc 5)  → 10
  (acc 2)  → 12

  acc:sum  → 12
  acc:x    → nil

  acc:acc  → (lambda (acc:x) (inc acc:sum acc:x))

  sum      → 0

The function works by creating a context and default functor from the name of the function. The value of acc:sum is initialized to 0 copying the value of MAIN:sum.

Using acc as a prototype, new statically scoped functions can be created:

  (new 'acc 'myacc)
  
  (myacc 3) → 15

The new function will start of with myacc:sum as present in acc:sum when doing the copy with new.

Using a more complex method, a def-static can be defined as a macro which can be used like the normal define function:

  ;; define static functions (use only in context MAIN)
  ;;
  ;; Example:
  ;;
  ;; (def-static (foo x) (+ x x))
  ;;
  ;; foo:foo   → (lambda (foo:x) (+ foo:x foo:x))
  ;;
  ;; (foo 10)  → 20
  ;;
  (define-macro (def-static)
     (let (temp (append (lambda) (list (1 (args 0)) (args 1))))
         (def-new 'temp (sym (args 0 0) (args 0 0)))))

  (def-static (acc x)
         (inc sum x))

  (acc 5)  → 5
  (acc 5)  → 10
  (acc 2)  → 12
    
  acc:sum  → 12
  acc:x    → nil

The macro def-static first creates a lambda expression of the function to be defined in the current name space and assigns it to the variable temp. In a second step the lambda function in temp is copied to its own name space. This happens by assigning it to the default functor acc:acc symbol built from the name of the function.