;; @module util
;; @author Jeff Ober , Kanen Flowers
;; @version 2.0
;; @location http://static.artfulcode.net/newlisp/util.lsp
;; @package http://static.artfulcode.net/newlisp/util.qwerty
;; @description Various functions that the other libraries depend on (updated for newlisp 10).
;; Various helpful utilities for newLISP. Requires newlisp 10+.
;;
;;
Version history
;; 2.1
;; • added with-open-device, partial
;; • added make-array, array-iter and array-map
;;
;; 2.0
;; • updated for newlisp 10 (backwards-incompatible)
;; • refactored assoc? (now permits any key that satisfies 'atom?')
;; • get-assoc is now a regular function whose arguments must be quoted
;; • slot functions removed as new association list features make them redundant
;; • dict-keys refactored and renamed to keys
;; • refactored dokeys for a slight speed improvement
;;
;; 1.4
;; • added
;; • now supports string keys
;; • fixed bug when calling from within a context
;; • now permits renaming of variables in binding to avoid clashes in nested calls
;; • added
;; • added
;; • added
;;
;; 1.3
;; • now supports assoc data in the format '(key val-1 val-2 ...)' and '(key val)
;;
;; 1.2
;; • fixed bug that caused to return only the first value of a list
;;
;; 1.1
;; • added , , and
;;
;; 1.0
;; • initial release
;; @syntax (type-of
;; @example
;; (define dict:dict)
;; (dict "x" 10)
;; (dict "y" 20)
;; (dokeys (key dict)
;; (println key ": " (dict key)))
;; => x: 10
;; => y: 20
(define-macro (dokeys)
(letex ((var (args 0 0)) (ctx (args 0 1)) (body (cons 'begin (rest (args)))))
(dolist (key (keys ctx))
(setf var key)
body)))
(global 'dokeys)
;; @syntax (make-array )
;; @param the size of the new array
;; @param when true (nil by default), passes the position index to
;;
Generates a new one-dimensional array of size and initializes
;; each array index by repeatedly calling . The current index is
;; available in $idx.
;; @example
;; (setf arr (make-array 4 (gensym)))
;; => '(gensym-1 gensym-2 gensym-3 gensym-4)
(define (make-array size fun , arr i)
(setf arr (array size) i -1)
(until (= (inc i) size)
(setf (arr i) (fun)))
arr)
(global 'make-array)
;; @syntax (array-iter )
;; @param a function to call on each index of the array
;; @param an array
;;
Calls on each index of . Returns the value of the
;; last iteration. The current index is available in $idx.
;; @example
;; (setf arr (array 4 (sequence 0 4))) ; => (0 1 2 3)
;; (array-iter (fn (i) (println (+ i $idx))) arr)
;; 0
;; 2
;; 4
;; 6
(define (array-iter fun arr , size i)
(setf i -1 size (length arr))
(until (= (inc i) size)
(fun (arr i))))
(global 'array-iter)
;; @syntax (array-map ) !
;; @param a function to call on each index of the array
;; @param an array
;;
Similar to the built-in function map, array-map applies to each
;; index of . array-map modifies in place.
Evaluates with as the default device.
;; Catches errors during evaluation and closes once complete,
;; restoring the previous default device.
;; @example
;; ; read one line from file and close
;; (with-open-device (open "somefile.txt")
;; (println (read-line)))
(define-macro (with-open-device)
(let ((old-dev (device)) (dev (eval (args 0))) (return) (result))
(device dev)
(setf return (catch (eval (cons begin (rest (args)))) 'result))
(close (device))
(device old-dev)
(if return result (throw-error result))))
(global 'with-open-device)
;; @syntax (partial )
;; @param a function to be partially applied
;; @param an expression to replace the first argument of
;;
Returns a new function that has been partially applied to . Unlike
;; curry, partial evaluates its arguments and does no damage to the parameter
;; list of the resulting function, which continues to accept the rest of the
;; parameters it would typically accept. This is particularly useful to fudge
;; closures over FOOP methods by partially applying them to their instances.
;; Note that macros and functions that do not evaluate their arguments may not
;; be partially applied, due to the use of the apply function in this
;; implementation.
;; @example
;; (define (foo a b c)
;; (join (list "foo" a b c) "|"))
;; (setf foobar (partial foo "bar"))
;; (foobar "baz" "bat") ; => "foo|bar|baz|bat"
(define (partial func arg)
(letex ((func func) (arg arg))
(lambda ()
(apply func (cons 'arg (args))))))
(global 'partial)