(chapter-start ‘nydp-core “essential functions for getting anything done”)
(def iso (x y)
(or (eq? x y) (and (pair? x) (pair? y) (eq? (len x) (len y)) (iso (car x) (car y)) (iso (cdr x) (cdr y)))))
(def num? (arg) (comment “true if arg is a number”) (isa ‘number arg)) (def string? (arg) (comment “true if arg is a string”) (isa ’string arg))
;; this is useful sometimes when ‘expr can’t stand on its own due to lexical ambiguity, most often in string interpolations ;; for example, in “hello ~person, how are you”, the parser will try to interpolate the symbol “person,” rather than the ;; expected “person”. In this case, use “hello ~(just person), how are you” (mac just (expr) expr)
(def quotify (arg) ‘(quote ,arg))
;; return a function that always returns ‘arg, similar to K in SKI calculus (defmemo k (arg) (fn nil arg))
;; return the length of ‘things where ’things may be nil, a string, list or hash ;; length of nil is zero, length of hash is number of keys, length of string ;; is number of characters, length of list is number of direct items - no recursive counting (def len (things)
(chapter list-manipulation) (chapter string-manipulation) (chapter hash-manipulation) (if (pair? things) (list-length things) (string? things) (string-length things) (hash? things) (list-length:hash-keys things) things nil 0))
(assign dynamics (hash))
;; creates a dynamic variable. (mac dynamic (name initial)
(let with-mac-name (sym:+ "w/" name) (w/uniq prev `(do (hash-set dynamics ',name t) (mac ,with-mac-name (new-value . body) (w/uniq result `(let ,',prev (hash-get (thread-locals) ',',name) (hash-set (thread-locals) ',',name ,new-value) (returning (do ,@body) (hash-set (thread-locals) ',',name ,',prev))))) ,(if initial `(hash-set (thread-locals) ',name ,initial)) (def ,name () (hash-get (thread-locals) ',name))))))
;; overrides ‘privately defined earlier in documentation manager (dynamic privately)
;; suppress documentation of anything defined in ‘body (mac in-private body
`(w/privately t ,@body))
;; a macro wrapper for ‘map ;; ’things is a list, ‘x is the name of a variable, and ’expr ;; is evaluated and collected for each ‘x in ’things ;; usage: (mapx items v (to-string v)) equivalent to (map to-string items) (mac mapx (things x expr)
(chapter list-manipulation) `(map (fun (,x) ,expr) ,things))
;; ‘t if ’thing is not nil or a list or a hash (def atom? (thing)
(chapter nydp-core) (and thing (!pair? thing) (!hash? thing)))
(def empty? (things)
; t if it's nil or an empty list, string, or hash ; nil otherwise (chapter list-manipulation) (chapter string-manipulation) (chapter hash-manipulation) (let l (len things) (and l (eq? l 0))))
(def present? (thing)
; t if it's a symbol or number, or a non-empty string, list or hash ; nil otherwise (chapter list-manipulation) (chapter string-manipulation) (chapter hash-manipulation) (!empty? thing))
;; returns the first non-empty item in ‘args ;; mac equivalent of (detect present? args) ;; useful to obtain a non-blank value from a set of variables, for example ;; (%span.name (dp {first} {last} {email} “unknown”)) (mac dp args
(if args (w/uniq nearg `(let ,nearg ,(car args) (if (empty? ,nearg) (dp ,@(cdr args)) ,nearg))) nil))
;; returns a function that returns a number sequence. Example: ;; (let c (counter) ;; (p ©) ;;=> 0 ;; (p ©) ;;=> 1 ;; (p ©)) ;;=> 2 ;; ;; see also ‘seqf which does almost exactly the same thing (def counter ()
(let i -1 (fn () (++ i))))