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.