Sl-sh

Documentation structure for each form

form name type (see: Type forms)
namespace (fully qualified names are of format namespace::symbol) usage
example code if exists

Table of Contents

Char forms

char-lower, char-upper, char-whitespace?

Conditional forms

<, <=, =, >, >=, and, cond, if, match, not, null, or, when

Core forms

*collection-src*, *core-src*, *getopts-src*, *iterator-src*, *lib-src*, *seq-src*, *shell-read-src*, *shell-src*, *slsh-std-src*, *slshrc-src*, *struct-src*, *test-src*, and-let*, apply, back-quote, block, dec!, def, def?, defmacro, defn, do, doc, doc-raw, dotimes, dotimes-i, dyn, eprint, eprintln, err, error-stack-off, error-stack-on, eval, expand-macro, expand-macro-all, expand-macro1, fn, format, gensym, get-error, identity, inc!, intern-stats, len0?, len>0?, length, let, let*, loop, macro, maybe-docstring?, meta-add-tags, meta-column-no, meta-file-name, meta-line-no, meta-tag?, nsubstitute!, occurs, print, print-error, println, quote, reader-macro-dot, recur, ref, return-from, set!, substitute, undef, unwind-protect, values, values-length, values-nth, var

File forms

cd, close, collate-fs-changes, flush, fs-accessed, fs-base, fs-crawl, fs-dir?, fs-exists?, fs-file?, fs-len, fs-modified, fs-notify, fs-parent, fs-rm, fs-same?, get-temp, get-temp-file, glob, open, read, read-all, read-line, temp-dir, with-temp, with-temp-file, write-line, write-string

Globals forms

*last-command*, *last-status*, *repl-settings*, *std-lib-namespaces*, *std-lib-syms-hash*

Hashmap forms

hash-clear!, hash-get, hash-haskey, hash-keys, hash-remove!, hash-set!, make-hash

Iterator forms

append, append-iter, append-to!, collect, collect-str, collect-vec, double-ended-iter?, double-ended-iterator, empty?, file-iter, filter, filter-iter, for, for-i, interleave, interleave-iter, iter, iter?, iterator, list-iter, map, map-iter, meld, meld-iter, next!, nth, range, range-iter, reduce, reduce-times, repeat, repeat-iter, reverse, reverse-iter, slice, slice-iter, string-iter, take, take-iter, vec-iter

Logger forms

logger

Math forms

%, *, *euler*, *pi*, +, -, /, 2pow, abs, arccos, arcsin, arctan, ceil, cos, exp, floor, fract, lne, log, log2, pow, round, sin, sqrt, tan, to-degrees, to-radians

Namespace forms

ns-auto-export, ns-create, ns-enter, ns-exists?, ns-export, ns-import, ns-list, ns-pop, ns-push, ns-symbols

Pair forms

car, cdr, join, list, xar!, xdr!

Pair-ext forms

caaar, caadr, caar, cadar, cadddr, caddr, cadr, cdaar, cdadr, cdar, cddar, cdddr, cddr

Random forms

probool, random, random-str

Regex forms

make-regex, re-color, re-find, re-find-all, re-match, re-replace

Root forms

*read-table*, *read-table-terminal*, *string-read-table*

Scripting forms

*load-path*, load, mkli

Sequence forms

butlast, collect-copy, empty-seq?, first, in?, last, non-empty-seq?, qsort, rest, seq-for, seq?, setnth!

Shell forms

*stderr*, *stdin*, *stdout*, alias, alias?, bg-color-rgb, clear-dirs, dirs, epoch, err>, err>>, err>null, fc, fg-color-rgb, get-dirs, getopts, getopts-help, history-context, history-empty?, history-length, history-nth, history-push, history-push-throwaway, let-env, out-err>, out-err>>, out-err>null, out>, out>>, out>null, popd, prompt, pushd, register-alias, set-dirs-max, syntax-off, syntax-on, sys-command?, timer, unalias, unregister-alias, version

Stats forms

first-quartile, max, mean, median, min, mode, std-dev, summary-stats, third-quartile

String forms

char->int, codepoints, do-unstr, str, str-append, str-bytes, str-cat-list, str-clear!, str-contains, str-empty?, str-iter-empty?, str-iter-next!, str-iter-peek, str-iter-start, str-lower, str-ltrim, str-map, str-nth, str-push!, str-replace, str-rsplit, str-rsplitn, str-rtrim, str-split, str-splitn, str-starts-with, str-sub, str-trim, str-upper, with-padding

Struct forms

defstruct, deftrait

System forms

bg, exit, export, fg, fork, get-env, get-pid, jobs, pid, pipe, reap-jobs, sleep, syscall, time, umask, unexport, wait

Test forms

assert-equal, assert-error, assert-error-msg, assert-false, assert-not-equal, assert-true, run-example

Threading-macros forms

->, ->>, chain, chain-and, chain-when

Type forms

boolean?, builtin?, char?, false?, falsey?, file?, float->int, float?, func?, hash?, int->float, int?, lambda?, list?, macro?, nil?, none?, pair?, process?, regex?, some?, str->float, str->int, string?, sym, sym->str, symbol?, true?, type, values?, vec?

Vector forms

make-vec, vec, vec-clear!, vec-empty?, vec-insert!, vec-nth, vec-pop!, vec-push!, vec-remove!, vec-set!, vec-slice

Documentation

Char forms

char-lower Type: Function
root::char-lower Usage: (char-lower char) -> char

Get lower case (utf) character for a character.

Example:
(test::assert-equal #\a (char-lower #\A))
(test::assert-equal #\a (char-lower #\a))
(test::assert-not-equal #\a (char-lower #\Z))
(test::assert-equal #\λ (char-lower #\Λ))
(test::assert-equal #\λ (char-lower #\λ))


char-upper Type: Function
root::char-upper Usage: (char-upper char) -> char

Get upper case (utf) character for a character.

Example:
(test::assert-equal #\A (char-upper #\A))
(test::assert-equal #\A (char-upper #\a))
(test::assert-not-equal #\A (char-upper #\Z))
(test::assert-equal #\Λ (char-upper #\λ))
(test::assert-equal #\Λ (char-upper #\Λ))


char-whitespace? Type: Function
root::char-whitespace? Usage: (char-whitespace? char) -> t/nil

Returns true if a character is whitespace, false/nil otherwise.

Example:
(test::assert-true (char-whitespace? #\ ))
(test::assert-true (char-whitespace? #\tab))
(test::assert-false (char-whitespace? #\s))


Conditional forms

< Type: Function
root::< Usage: (< val0 ... valN)

Less than. Works for int, float or string.

Example:
(test::assert-true (< 1 2))
(test::assert-true (< 1 2 3 4))
(test::assert-false (< 2 2))
(test::assert-false (< 2 2 2))
(test::assert-false (< 2 2 3))
(test::assert-true (< 1.0 2.0))
(test::assert-false (< 2.0 2.0))
(test::assert-false (< 2.0 2.0 2.0))
(test::assert-false (< 2.0 2.0 3.0))
(test::assert-false (< 2.1 2.0 3.0))
(test::assert-false (< 2 1))
(test::assert-false (< 3 2 3))
(test::assert-true (< "aaa" "aab"))
(test::assert-false (< "aaa" "aaa"))
(test::assert-true (< "aaa" "aab" "ccc"))
(test::assert-false (< "baa" "aab"))


<= Type: Function
root::<= Usage: (<= val0 ... valN)

Less than or equal. Works for int, float or string.

Example:
(test::assert-true (<= 1 2))
(test::assert-true (<= 2 2))
(test::assert-true (<= 2 2 2))
(test::assert-true (<= 2 2 3))
(test::assert-true (<= 1.0 2.0))
(test::assert-true (<= 2.0 2.0))
(test::assert-true (<= 2.0 2.0 2.0))
(test::assert-true (<= 2.0 2.0 3.0))
(test::assert-false (<= 2.1 2.0 3.0))
(test::assert-false (<= 2 1))
(test::assert-false (<= 3 2 3))
(test::assert-true (<= "aaa" "aab"))
(test::assert-true (<= "aaa" "aaa"))
(test::assert-true (<= "aaa" "aab" "ccc"))
(test::assert-false (<= "baa" "aab"))


= Type: Function
root::= Usage: (= val0 ... valN)

Equals. Works for int, float or string.

Example:
(test::assert-false (= 1 2))
(test::assert-true (= 2 2))
(test::assert-true (= 2 2 2))
(test::assert-false (= 3 2 2))
(test::assert-false (= 3.0 2.0))
(test::assert-true (= 2.0 2.0))
(test::assert-true (= 2.0 2.0 2.0))
(test::assert-false (= 3.0 2.0 2.0))
(test::assert-false (= 2.1 2.0 3.0))
(test::assert-false (= 2 1))
(test::assert-false (= 3 2 1))
(test::assert-false (= 1.1 1.0))
(test::assert-true (= 1.1 1.1))
(test::assert-false (= 3 2 3))
(test::assert-false (= "aab" "aaa"))
(test::assert-true (= "aaa" "aaa"))
(test::assert-true (= "aaa" "aaa" "aaa"))
(test::assert-false (= "aaa" "aaaa" "aaa"))
(test::assert-false (= "ccc" "aab" "aaa"))
(test::assert-false (= "aaa" "aab"))


> Type: Function
root::> Usage: (> val0 ... valN)

Greater than. Works for int, float or string.

Example:
(test::assert-false (> 1 2))
(test::assert-false (> 2 2))
(test::assert-false (> 2 2 2))
(test::assert-false (> 3 2 2))
(test::assert-true (> 3.0 2.0))
(test::assert-false (> 2.0 2.0))
(test::assert-false (> 2.0 2.0 2.0))
(test::assert-false (> 3.0 2.0 2.0))
(test::assert-false (> 2.1 2.0 3.0))
(test::assert-true (> 2 1))
(test::assert-true (> 3 2 1))
(test::assert-true (> 1.1 1.0))
(test::assert-false (> 3 2 3))
(test::assert-true (> "aab" "aaa"))
(test::assert-false (> "aaa" "aaa"))
(test::assert-true (> "ccc" "aab" "aaa"))
(test::assert-false (> "aaa" "aab"))


>= Type: Function
root::>= Usage: (>= val0 ... valN)

Greater than or equal. Works for int, float or string.

Example:
(test::assert-false (>= 1 2))
(test::assert-true (>= 2 2))
(test::assert-true (>= 2 2 2))
(test::assert-true (>= 3 2 2))
(test::assert-true (>= 3.0 2.0))
(test::assert-true (>= 2.0 2.0))
(test::assert-true (>= 2.0 2.0 2.0))
(test::assert-true (>= 3.0 2.0 2.0))
(test::assert-false (>= 2.1 2.0 3.0))
(test::assert-true (>= 2 1))
(test::assert-true (>= 1.1 1.0))
(test::assert-false (>= 3 2 3))
(test::assert-true (>= "aab" "aaa"))
(test::assert-true (>= "aaa" "aaa"))
(test::assert-true (>= "ccc" "aab" "aaa"))
(test::assert-false (>= "aaa" "aab"))


and Type: SpecialForm
root::and Usage: (and exp0 ... expN) -> [false(#f) or expN result]

Evaluates each form until one produces nil or false(#f), produces false(#f) if any form is nil/#f or the result of the last expression. The and form will stop evaluating when the first expression produces nil/#f.

Example:
(test::assert-equal #f (and nil (err "and- can not happen")))
(test::assert-equal #f (and #f (err "and- can not happen")))
(test::assert-equal "and- done" (and #t "and- done"))
(test::assert-equal "and- done" (and #t #t "and- done"))
(test::assert-equal 6 (and #t #t (+ 1 2 3)))
(test::assert-equal 6 (and (/ 10 5) (* 5 2) (+ 1 2 3)))


cond Type: Macro
root::cond Usage: (cond ((test form*)*) -> result

Evaluate each test in order. If it is true then evaluate the form(s) in an implicit do and return the result. Stop evaluting at the first true test. Return nil if no conditions are true.

Example:
(defn select-option (a)
(cond ((= a 1) "opt-one")
((= a 2) (set! b 5) "opt-two")
((= a 3) (str "opt" "-three"))))
(defn select-option-def (a)
(cond ((= a 1) "opt-one")
((= a 2) "opt-two")
((= a 3) (str "opt" "-three"))
(#t "default")))
(def b 0)
(assert-equal "opt-one" (select-option 1))
(assert-equal b 0)
(assert-equal "opt-two" (select-option 2))
(assert-equal b 5)
(assert-equal "opt-three" (select-option 3))
(assert-equal nil (select-option 4))
(assert-equal "opt-one" (select-option-def 1))
(assert-equal "opt-two" (select-option-def 2))
(assert-equal "opt-three" (select-option-def 3))
(assert-equal "default" (select-option-def 4))


if Type: SpecialForm
root::if Usage: (if p1 a1 p2 a2 ... pn an?) -> [evaled form result]

If conditional. Will evaluate p1 and if true (i.e. not nil or false) then return the evaluation of a1, if falsey(i.e. nil or false) evaluate p2 and so on. On an odd number of arguments (an is missing) then evaluate and return pn. Return false(#f) if no predicate is true. This degenerates into the traditional (if predicate then-form else-form). NOTE: Both nil and false(#f) are ‘falsey’ for the purposes of if.

Example:
(def test-if-one
(if #t "ONE TRUE" "ONE FALSE"))
(def test-if-two
(if nil "TWO TRUE" "TWO FALSE"))
(def test-if-three
(if #f "THREE TRUE" "THREE FALSE"))
(test::assert-equal "ONE TRUE" test-if-one)
(test::assert-equal "TWO FALSE" test-if-two)
(test::assert-equal "THREE FALSE" test-if-three)
(def test-if-one2
(if #t "ONE2 TRUE"))
(def test-if-two2
(if nil "TWO2 TRUE"))
(def test-if-three2
(if #f "THREE2 TRUE"))
(test::assert-equal "ONE2 TRUE" test-if-one2)
(test::assert-equal #f test-if-two2)
(test::assert-equal #f test-if-three2)
(def test-if-one2
(if nil "ONE FALSE" #t "ONE TRUE" #t "ONE TRUE2"))
(def test-if-two2
(if nil "TWO TRUE" #f "TWO FALSE" #t "TWO TRUE2"))
(def test-if-three2
(if #f "THREE TRUE" nil "THREE FALSE" "THREE DEFAULT"))
(test::assert-equal "ONE TRUE" test-if-one2)
(test::assert-equal "TWO TRUE2" test-if-two2)
(test::assert-equal "THREE DEFAULT" test-if-three2)
(test::assert-equal nil (if nil))
(test::assert-equal #f (if nil #t nil #t nil t))


match Type: Macro
root::match Usage: (match condition (value form*)*) -> result

Evaluate condition and look for matching value in each branch of type (value form*). Form(s) will be wrapped in an implicit do. Use nil to take action if no match (encouraged!).

Example:
(defn select-option (a)
(match a (1 "opt-one")
(2 (set! b 5) "opt-two")
(3 (str "opt" "-three"))))
(defn select-option-def (a)
(match a (1 "opt-one")
(2 "opt-two")
(3 (str "opt" "-three"))
(nil "default")))
(def b 0)
(assert-equal b 0)
(assert-equal "opt-one" (select-option 1))
(assert-equal "opt-two" (select-option 2))
(assert-equal b 5)
(assert-equal "opt-three" (select-option 3))
(assert-equal #f (select-option 4))
(assert-equal "opt-one" (select-option-def 1))
(assert-equal "opt-two" (select-option-def 2))
(assert-equal "opt-three" (select-option-def 3))
(assert-equal "default" (select-option-def 4))


not Type: Function
root::not Usage: (not expression)

Return true(#t) if expression is nil, false(#f) otherwise.

Example:
(test::assert-true (not nil))
(test::assert-false (not 10))
(test::assert-false (not #t))
(test::assert-false (not (+ 1 2 3)))


null Type: Function
root::null Usage: (null expression)

Return true(#t) if expression is nil (null).

Example:
(test::assert-true (null nil))
(test::assert-false (null 10))
(test::assert-false (null #t))
(test::assert-false (null (+ 1 2 3)))


or Type: SpecialForm
root::or Usage: (or exp0 ... expN) -> [false(#f) or first non nil expression]

Evaluates each form until one produces a non-nil/non-false result, produces #f if all expressions are ‘falsey’. The or form will stop evaluating when the first expression produces non-nil/false.

Example:
(test::assert-true (or nil nil #t (err "and- can not happen")))
(test::assert-true (or #f nil #t (err "and- can not happen")))
(test::assert-true (or #f #f #t (err "and- can not happen")))
(test::assert-equal #f (or nil nil nil))
(test::assert-equal #f (or #f nil nil))
(test::assert-equal #f (or #f nil #f))
(test::assert-equal #f (or #f #f #f))
(test::assert-equal "or- done" (or nil "or- done"))
(test::assert-equal "or- done" (or nil nil "or- done"))
(test::assert-equal 6 (or nil nil (+ 1 2 3)))
(test::assert-equal 2 (or (/ 10 5) (* 5 2) (+ 1 2 3)))


when Type: Macro
root::when Usage: (when provided-condition if-true)

when is a convenience function used to check a form, provided-condition, and run some form, if-true, if provided-condition evaluates to true.

Example:
(assert-true (when #t #t))
(assert-false (when #t nil))
(assert-false (when nil nil))


Core forms

*collection-src* Type: String
root::*collection-src* Usage: (print *collection-src*)

The builtin source code for collection.lisp.

Example:
;(print *collection-src*)
#t


*core-src* Type: String
root::*core-src* Usage: (print *core-src*)

The builtin source code for core.lisp.

Example:
;(print *core-src*)
#t


*getopts-src* Type: String
root::*getopts-src* Usage: (print *getopts-src*)

The builtin source code for shell.lisp.

Example:
;(print *getopts-src*)
#t


*iterator-src* Type: String
root::*iterator-src* Usage: (print *iterator-src*)

The builtin source code for iterator.lisp.

Example:
;(print *iterator-src*)
#t


*lib-src* Type: String
root::*lib-src* Usage: (print *lib-src*)

The builtin source code for lib.lisp.

Example:
;(print *lib-src*)
#t


*seq-src* Type: String
root::*seq-src* Usage: (print *seq-src*)

The builtin source code for seq.lisp.

Example:
;(print *seq-src*)
#t


*shell-read-src* Type: String
root::*shell-read-src* Usage: (print *shell-read-src*)

The builtin source code for shell-read.lisp.

Example:
;(print *shell-read-src*)
#t


*shell-src* Type: String
root::*shell-src* Usage: (print *shell-src*)

The builtin source code for shell.lisp.

Example:
;(print *shell-src*)
#t


*slsh-std-src* Type: String
root::*slsh-std-src* Usage: (print *slsh-std-src*)

The builtin source code for slsh-std.lisp.

Example:
;(print *slsh-std-src*)
#t


*slshrc-src* Type: String
root::*slshrc-src* Usage: (print *slshrc-src*)

The builtin source code for slshrc.

Example:
;(print *slshrc-src*)
#t


*struct-src* Type: String
root::*struct-src* Usage: (print *struct-src*)

The builtin source code for struct.lisp.

Example:
;(print *struct-src*)
#t


*test-src* Type: String
root::*test-src* Usage: (print *test-src*)

The builtin source code for test.lisp.

Example:
;(print *test-src*)
#t


and-let* Type: Macro
root::and-let* Usage: (and-let* vals &rest let-body)

Takes list, vals, of form ((binding0 sexp0) (binding1 sexp1) …) checking if result of each sexp evaluates to false, short circuiting and returning nil if so. If all vals bindings evaluate to true, then the let-body is evaluated with all values of binding bound to the result of the evaluation of sexp. Sexps can reference bindings from previous items in the list of vals. If no let-body is supplied the last binding in the list of vals is returned.

Example:
(test::assert-equal "charlie bravo alpha."
(and-let* ((val (str "alpha."))
(other-val (str "bravo " val)))
(str "charlie " other-val)) "]")
(test::assert-equal "alpha, bravo." (and-let* ((val (do
(str "bravo.")))
(other-val (do
(str "alpha, " val))))))
(test::assert-false (and-let* ((val (do (str "alpha, ") nil))
(other-val (do (str "bravo " val))))))
(test::assert-false (and-let* ((a-list (list 1 2 3 4 5 6 7 8))
(evens (filter (fn (x) (= 0 (% x 2))) a-list))
(doubled (map (fn (x) (* x 2)) evens))
(odds (collect (filter (fn (x) (= 1 (% x 2))) doubled))))
#t))


apply Type: Function
root::apply Usage: (apply function arg* list)

Call the provided function with the supplied arguments, last is a list that will be expanded.

Example:
(def test-apply-one (apply str '(\"O\" \"NE\")))
(test::assert-equal \"ONE\" test-apply-one)
(test::assert-equal 10 (apply + 1 '(2 7)))


back-quote Type: SpecialForm
root::back-quote Usage: `expression -> expression

Return expression without evaluation. Always use the ` reader macro or expansion will not work (i.e. (back-quote expression) will not do , expansion). Backquote (unlike quote) allows for symbol/form evaluation using , or ,@.

Example:
(test::assert-equal (list 1 2 3) `(1 2 3))
(test::assert-equal `(1 2 3) '(1 2 3))
(def test-bquote-one 1)
(def test-bquote-list '(1 2 3))
(test::assert-equal (list 1 2 3) `(,test-bquote-one 2 3))
(test::assert-equal (list 1 2 3) `(,@test-bquote-list))


block Type: SpecialForm
root::block Usage: (block name form*)

Create a block with name (name is not evaluated), if no return-from encountered then return last expression (like do). Note: If the last expression in a block is a tail call then it can not use return-from since the tail call will leave the block and the return-from will not find it.

Example:
(test::assert-equal '(4 5) (block xxx '(1 2) (return-from xxx '(4 5)) '(a b) '(2 3)))
(test::assert-equal '(4 5) (block xxx '(1 2) (return-from nil '(4 5)) '(a b) '(2 3)))
(test::assert-equal '(5 6) (block xxx '(1 2) (block yyy (return-from xxx '(5 6)) '(a b)) '(2 3)))
(test::assert-equal '(5 6) (block xxx '(1 2) (block yyy ((fn (p) (return-from xxx p)) '(5 6)) '(a b)) '(2 3)))
(test::assert-equal '(2 3) (block xxx '(1 2) (block yyy (return-from yyy #t) '(a b)) '(2 3)))
(test::assert-equal '(5 6) (block yyy ((fn (p) (return-from yyy p)) '(5 6)) '(a b)) '(2 3))
(test::assert-equal 2
(block forloop
(for item in '(1 2 3)
(when (= 2 item)
(return-from forloop item)))
nil)) ; This nil keeps the for loop from being a tail call.


dec! Type: Macro
root::dec! Usage: (dec! symbol [number]) -> new value

Decrement the value in symbol by one or the optional number

Example:
(def *dec-test* 5)
(test::assert-equal 4 (dec! *dec-test*))
(test::assert-equal 4 *dec-test*)
(test::assert-error (dec! *dec-test* "xxx"))
(test::assert-equal 1 (dec! *dec-test* 3))
(test::assert-equal 1 *dec-test*)
(def *dec-test* "xxx")
(test::assert-error (dec! *dec-test*))
(let ((dec-test 5))
(test::assert-equal 4 (dec! dec-test))
(test::assert-equal 4 dec-test)
(test::assert-equal 1 (dec! dec-test 3))
(test::assert-equal 1 dec-test))


def Type: SpecialForm
root::def Usage: (def symbol doc_string? expression) -> expression

Adds an expression to the current namespace. Return the expression that was defined. Symbol is not evaluted. Can take an option doc string (docstrings can only be set on namespaced (global) symbols).

Example:
(def test-do-one nil)
(def test-do-two nil)
(def test-do-three (do (set! test-do-one "One")(set! test-do-two "Two")"Three"))
(test::assert-equal "One" test-do-one)
(test::assert-equal "Two" test-do-two)
(test::assert-equal "Three" test-do-three)
(let ((test-do-one nil))
; Add this to tthe let's scope (shadow the outer test-do-two).
(test::assert-equal "Default" (def ns::test-do-four "Default"))
; set the currently scoped value.
(set! test-do-one "1111")
(set! test-do-two "2222")
(test::assert-equal "1111" test-do-one)
(test::assert-equal "2222" test-do-two)
(test::assert-equal "Default" test-do-four))
; Original outer scope not changed.
(test::assert-equal "One" test-do-one)
(test::assert-equal "Default" test-do-four)
;(def (sym "test-do-one") "do one")
(test::assert-error (def (sym "test-do-one") "do one"))
;(test::assert-equal "do one" test-do-one)
(test::assert-error (def (sym->str test-do-one) "do one 2"))


def? Type: SpecialForm
root::def? Usage: (def? expression) -> t\|nil

Return true if is a defined symbol (bound within the current scope). If expression is a symbol it is not evaluted and if a list it is evaluted to produce a symbol.

Example:
(def test-is-def #t)
(def test-is-def2 'test-is-def)
(test::assert-true (def? test-is-def))
(test::assert-true (def? (sym "test-is-def")))
(test::assert-true (def? (ref test-is-def2)))
(test::assert-false (def? test-is-def-not-defined))
(test::assert-false (def? (sym "test-is-def-not-defined")))
(test::assert-error (def? (ref test-is-def)))


defmacro Type: Macro
root::defmacro Usage: (defmacro name doc_string? argument_list body)

Create a macro and bind it to a symbol in the current scope.

Example:
(defmacro test-mac (x) (let ((y (+ (ref (ref x)) 1))) `(set! ,x ,y)))
(def test-mac-x 2)
(test-mac test-mac-x)
(test::assert-equal 3 test-mac-x)
(defmacro test-mac (x) `(set! ,x 15))
(test-mac test-mac-x)
(test::assert-equal 15 test-mac-x)


defn Type: Macro
root::defn Usage: (defn name &rest args)

Define a named function in the current namespace.

Example:
(defn defn-test (x y) (+ x y))
(test::assert-equal 5 (defn-test 2 3))
(defn defn-test (x y) (set! x (* x 2))(+ x y))
(test::assert-equal 7 (defn-test 2 3))
(defn defn-test (x y))
(test::assert-false (defn-test 2 3))
(defn defn-test (x y) #t)
(test::assert-true (defn-test 2 3))


do Type: SpecialForm
root::do Usage: (do exp0 ... expN) -> expN

Evaluatate each form and return the last.

Example:
(def test-do-one nil)
(def test-do-two nil)
(def test-do-three (do (set! test-do-one "One")(set! test-do-two "Two")"Three"))
(test::assert-equal "One" test-do-one)
(test::assert-equal "Two" test-do-two)
(test::assert-equal "Three" test-do-three)


doc Type: Function
root::doc Usage: (doc symbol)

Return the doc string for a symbol or nil if no string.

Example:
;(doc 'car)
#t


doc-raw Type: Function
root::doc-raw Usage: (doc-raw symbol)

Return the raw (unexpanded) doc string for a symbol or nil if no string.

Example:
;(doc-raw 'car)
#t


dotimes Type: Macro
root::dotimes Usage: (dotimes times body)

Evaluate body a number of times equal to times’ numerical value.

Example:
(def i 0)
(dotimes 11 (set! i (+ 1 i)))
(assert-equal 11 i)


dotimes-i Type: Macro
root::dotimes-i Usage: (dotimes-i idx-bind times body)

Evaluate body a number of times equal to times’ numerical value. Includes an incrementing reference binding, idx-bind, accessible in body.

Example:
(def i 0)
(def i-tot 0)
(dotimes-i idx 11 (do (set! i-tot (+ idx i-tot))(set! i (+ 1 i))))
(assert-equal 11 i)
(assert-equal 55 i-tot)


dyn Type: Macro
root::dyn Usage: (dyn key value expression) -> result_of_expression

Creates a dynamic binding for key, assigns value to it and evals expression under it. Note that if key must be a symbol and is not evaluted. The binding is gone once the dyn form ends. This is basically a set! on the binding in an unwind protect to reset it when done. When used on a global will set the first binding found and reset it when done. Calls to dyn can be nested and previous dynamic values will be restored as interior dyn’s exit.

Example:
(defn test-dyn-fn () (print "Print dyn out"))
(dyn *stdout* (open "/tmp/sl-sh.dyn.test" :create :truncate) (test-dyn-fn))
(test::assert-equal "Print dyn out" (read-line (open "/tmp/sl-sh.dyn.test" :read)))


eprint Type: Function
root::eprint Usage: (eprint arg0 ... argN) -> nil

Print the arguments (as strings) to stderr.

Example:
; Use a file for stderr for test.
(dyn *stderr* (open "/tmp/sl-sh.eprint.test" :create :truncate) (do (eprint "eprint test out")(eprint " two") (close *stderr*)))
(test::assert-equal "eprint test out two" (read-line (open "/tmp/sl-sh.eprint.test" :read)))


eprintln Type: Function
root::eprintln Usage: (eprintln arg0 ... argN) -> nil

Print the arguments (as strings) to stderr and then a newline.

Example:
; Use a file for stderr for test.
(dyn *stderr* (open "/tmp/sl-sh.eprintln.test" :create :truncate) (do (eprintln "eprintln test out")(eprintln "line two") (close *stderr*)))
(def topen (open "/tmp/sl-sh.eprintln.test" :read))
(test::assert-equal "eprintln test out
" (read-line topen))
(test::assert-equal "line two
" (read-line topen))


err Type: Function
root::err Usage: (err string) -> raises an error

Raise an error with the supplied string.

Example:
(def test-err-err (get-error (err "Test Error")))
(test::assert-equal :error (car test-err-err))
(test::assert-equal "Test Error" (cadr test-err-err))


error-stack-off Type: Lambda
root::error-stack-off Usage: (error-stack-off)

Currently a no-op, used to turn off error stacks.

Example:
; no-op
(error-stack-off)


error-stack-on Type: Lambda
root::error-stack-on Usage: (error-stack-on)

Currently a no-op, used to turn on error stacks.

Example:
; no-op
(error-stack-on)


eval Type: Function
root::eval Usage: (eval expression)

Evaluate the provided expression. If expression is a string read it to make an ast first to evaluate otherwise evaluate the expression (note eval is a function not a special form, the provided expression will be evaluated as part of call).

Example:
(def test-eval-one nil)
(eval (read "(set! test-eval-one \"ONE\")"))
(test::assert-equal "ONE" test-eval-one)
(eval '(set! test-eval-one "TWO"))
(test::assert-equal "TWO" test-eval-one)


expand-macro Type: Function
root::expand-macro Usage: (expand-macro expression)

Expands a macro expression. If that expansion is also a macro then expand it recursively. Just returns the expression if not a macro.

Example:
(test::assert-equal '(def xx "value") (expand-macro '(def xx "value")))
(defmacro mac-test-for
(bind in in_list body) (do
(if (not (= in 'in)) (err "Invalid test-mac-for: (test-mac-for [v] in [iterator] (body))"))
`((fn (,bind)
(if (> (length ,in_list) 0)
(root::loop (plist) (,in_list) (do
(set! ,bind (root::first plist))
(,@body)
(if (> (length plist) 1) (recur (root::rest plist)))))))nil)))
(test::assert-equal '(
(fn
(i)
(if
(> (length '(1 2 3)) 0)
(root::loop
(plist)
('(1 2 3))
(do
(set! i (root::first plist)) nil
(if
(> (length plist) 1)
(recur (root::rest plist))))))) nil)
(expand-macro '(mac-test-for i in '(1 2 3) ())))
(test::assert-equal '(1 2 3) (expand-macro '(1 2 3)))


expand-macro-all Type: Function
root::expand-macro-all Usage: (expand-macro-all expression)

Expands a macro expression like expand-macro but also expand any embedded macros. Just returns the expression if not a macro.

Example:
(test::assert-equal '(def xx "value") (expand-macro-all '(def xx "value")))
(defmacro mac-test-loop
(params bindings body)
`((fn ,params ,body) ,@bindings))
(defmacro mac-test-for
(bind in in_list body) (do
(if (not (= in 'in)) (err "Invalid test-mac-for: (test-mac-for [v] in [iterator] (body))"))
`((fn (,bind)
(if (> (length ,in_list) 0)
(mac-test-loop (plist) (,in_list) (do
(set! ,bind (root::first plist))
(,@body)
(if (> (length plist) 1) (recur (root::rest plist)))))))nil)))
(test::assert-equal '(
(fn
(i)
(if
(> (length '(1 2 3)) 0)
(
(fn
(plist)
(do
(set! i (root::first plist)) nil
(if
(> (length plist) 1)
(recur (root::rest plist)))))
'(1 2 3)))) nil)
(expand-macro-all '(mac-test-for i in '(1 2 3) ())))
(test::assert-equal '(1 2 3) (expand-macro-all '(1 2 3)))


expand-macro1 Type: Function
root::expand-macro1 Usage: (expand-macro1 expression)

Expands a macro expression. Only expand the first macro. Just returns the expression if not a macro.

Example:
(test::assert-equal '(def xx "value") (expand-macro1 '(def xx "value")))
(defmacro mac-test-for
(bind in in_list body) (do
(if (not (= in 'in)) (err "Invalid test-mac-for: (test-mac-for [v] in [iterator] (body))"))
`((fn (,bind)
(if (> (length ,in_list) 0)
(root::loop (plist) (,in_list) (do
(set! ,bind (root::first plist))
(,@body)
(if (> (length plist) 1) (recur (root::rest plist)))))))nil)))
(test::assert-equal '((fn
(i)
(if
(> (length '(1 2 3)) 0)
(root::loop
(plist)
('(1 2 3))
(do
(set! i (root::first plist)) nil
(if
(> (length plist) 1)
(recur (root::rest plist)))))))nil)
(expand-macro1 '(mac-test-for i in '(1 2 3) ())))
(test::assert-equal '(1 2 3) (expand-macro1 '(1 2 3)))


fn Type: SpecialForm
root::fn Usage: (fn (param*) expr*) -> exprN

Create a function (lambda).

Example:
(def test-fn1 nil)
(def test-fn2 nil)
(def test-fn3 nil)
(def test-fn-empty ((fn ())))
(test::assert-false test-fn-empty)
((fn () (set! test-fn1 1)))
(test::assert-equal 1 test-fn1)
((fn () (set! test-fn1 10)(set! test-fn2 2)))
(test::assert-equal 10 test-fn1)
(test::assert-equal 2 test-fn2)
((fn () (set! test-fn1 11)(set! test-fn2 20)(set! test-fn3 3)))
(test::assert-equal 11 test-fn1)
(test::assert-equal 20 test-fn2)
(test::assert-equal 3 test-fn3)
((fn (x y z) (set! test-fn1 x)(set! test-fn2 y)(set! test-fn3 z)) 12 21 30)
(test::assert-equal 12 test-fn1)
(test::assert-equal 21 test-fn2)
(test::assert-equal 30 test-fn3)
(test::assert-equal 63 ((fn (x y z) (set! test-fn1 x)(set! test-fn2 y)(set! test-fn3 z)(+ x y z)) 12 21 30))


format Type: Function
root::format Usage: (format arg0 ... argN) -> string

Build a formatted string from arguments. Arguments will be turned into strings.

Example:
(test::assert-equal "stringsome" (format "string" "some"))
(test::assert-equal "string" (format "string" ""))
(test::assert-equal "string 50" (format "string" " " 50))
(test::assert-equal "string 50 100.5" (format "string" " " 50 " " 100.5))


gensym Type: Function
root::gensym Usage: (gensym) -> symbol

Generate a unique symbol. Gensym uses a prefix of gs@@ followed by an incrementing counter. It is useful to generate unique symbol names when writing macros (for instance).

Example:
(def test-gensym-one (gensym))
(def test-gensym-two (gensym))
(def test-gensym-three (gensym))
(test::assert-true (str-starts-with "gs@@" (sym->str test-gensym-one)))
(test::assert-true (str-starts-with "gs@@" (sym->str test-gensym-two)))
(test::assert-true (str-starts-with "gs@@" (sym->str test-gensym-three)))
(test::assert-true (symbol? (gensym)))
(test::assert-true (symbol? test-gensym-one))
(test::assert-true (symbol? test-gensym-two))
(test::assert-true (symbol? test-gensym-three))


get-error Type: Function
root::get-error Usage: (get-error exp0 ... expN) -> pair

Evaluate each form (like do) but on error return (:error msg backtrace) instead of aborting. On success return (:ok . expN-result). If there is no error will return the value of the last expression as the cdr of the pair. Always returns a pair with the first value either being :ok or :error.

Example:
(def get-error-t1 (get-error (err "Some Error")))
(test::assert-equal :error (car get-error-t1))
(test::assert-equal "Some Error" (cadr get-error-t1))
(test::assert-true (vec? (caddr get-error-t1)))
(test::assert-equal '(:ok . "Some String") (get-error "Some String"))
(test::assert-equal '(:ok . "Some Other String") (get-error (def test-get-error "Some ") (str test-get-error "Other String")))


identity Type: Lambda
root::identity Usage: (identity x)

Identity function.

Example:
(assert-equal 0 (identity 0))


inc! Type: Macro
root::inc! Usage: (inc! symbol [number]) -> new value

Increment the value in symbol by one or the optional number

Example:
(def *inc-test* 1)
(test::assert-equal 2 (inc! *inc-test*))
(test::assert-equal 2 *inc-test*)
(test::assert-equal 5 (inc! *inc-test* 3))
(test::assert-error (inc! *inc-test* "xxx"))
(test::assert-equal 5 *inc-test*)
(def *inc-test* "xxx")
(test::assert-error (inc! *inc-test*))
(let ((inc-test 1))
(test::assert-equal 2 (inc! inc-test))
(test::assert-equal 2 inc-test)
(test::assert-equal 5 (inc! inc-test 3))
(test::assert-equal 5 inc-test))


intern-stats Type: SpecialForm
root::intern-stats Usage: (intern-stats)

Prints the stats for interned symbols.

Example:
;(intern-stats)
#t


len0? Type: Macro
root::len0? Usage: (len0? thing)

Is the length of thing 0?

Example:
(assert-true (len0? nil))
(assert-true (len0? '()))
(assert-true (len0? (vec)))
(assert-true (len0? (str)))
(assert-true (len0? ""))
(assert-false (len0? '(1)))
(assert-false (len0? (vec 1 2)))
(assert-false (len0? "string"))


len>0? Type: Macro
root::len>0? Usage: (len>0? thing)

Is the length of thing greater than 0?

Example:
(assert-false (len>0? nil))
(assert-false (len>0? '()))
(assert-false (len>0? (vec)))
(assert-false (len>0? (str)))
(assert-false (len>0? ""))
(assert-true (len>0? '(1)))
(assert-true (len>0? (vec 1 2)))
(assert-true (len>0? "string"))


length Type: Function
root::length Usage: (length expression) -> int

Return length of supplied expression.

Example:
(test::assert-equal 0 (length nil))
(test::assert-equal 5 (length \"12345\"))
; Note the unicode symbol is only one char even though it is more then one byte.
(test::assert-equal 6 (length \"12345Σ\"))
(test::assert-equal 3 (length '(1 2 3)))
(test::assert-equal 3 (length '#(1 2 3)))
(test::assert-equal 3 (length (list 1 2 3)))
(test::assert-equal 3 (length (vec 1 2 3)))
(test::assert-error (length 100))
(test::assert-error (length 100.0))
(test::assert-error (length #\\x))


let Type: Macro
root::let Usage: (let vals &rest let-body)

Takes list, vals, of form ((binding0 sexp0) (binding1 sexp1) …) and evaluates let-body with all values of binding bound to the result of the evaluation of sexp.

Example:
(def test-do-one "One1")
(def test-do-two "Two1")
(def test-do-three (let ((test-do-one "One")) (set! test-do-two "Two")(test::assert-equal "One" test-do-one)"Three"))
(test::assert-equal "One1" test-do-one)
(test::assert-equal "Two" test-do-two)
(test::assert-equal "Three" test-do-three)
((fn (idx) (let ((v2 (+ idx 2))(v3 (+ idx 3)))
(test::assert-equal (+ idx 2) v2)
(test::assert-equal (+ idx 3) v3)
(if (< idx 5) (recur (+ idx 1)))))0)
((fn (idx) (let ((v2 (+ idx 2))(v3 (+ idx 3)))
(test::assert-equal (+ idx 2) v2)
(test::assert-equal (+ idx 3) v3)
(if (< idx 5) (this-fn (+ idx 1)))))0)


let* Type: Macro
root::let* Usage: (let* vals &rest let-body)

Takes list, vals, of form ((binding0 sexp0) (binding1 sexp1) …) and evaluates let-body with all values of binding bound to the result of the evaluation of sexp. Differs from let in that sexps can reference bindings from previous items in the list of vals.

Example:
(let* ((add-one (fn (x) (+ 1 x)))
(double-add (fn (x) (add-one (add-one x)))))
(test::assert-equal 4 (add-one 3))
(test::assert-equal 6 (double-add 4)))


loop Type: Macro
root::loop Usage: (loop params bindings &rest body)

Binds bindings to parameters in body. Use recur with desired bindings for subsequent iteration. Within the loop the lambda ‘break’ will end the loop, break can take an option argument that is what the loop produces (nil if no argument).

Example:
(def tot 0)
(loop (idx) (3) (do
(set! tot (+ tot 1))
(if (> idx 1) (recur (- idx 1)))))
(assert-equal 3 tot)
(def tot 0)
(loop (idx) (0)
(set! tot (+ tot 1))
(if (= idx 2) (break))
(recur (+ idx 1)))
(assert-equal 3 tot)
(assert-equal 11 (loop (idx) (0)
(if (= idx 2) (break 11))
(recur (+ idx 1))))
(assert-false (loop (idx) (0)
(if (= idx 2) (break))
(recur (+ idx 1))))
(assert-error (loop (idx) (0)
(if (= idx 2) (break 1 3))
(recur (+ idx 1))))


macro Type: SpecialForm
root::macro Usage: (macro (args) `(apply + ,@args))

Define an anonymous macro.

Example:
(def test-macro1 nil)
(def test-macro2 nil)
(def test-macro-empty (macro ()))
(test::assert-false (test-macro-empty))
(def test-mac nil)
(def mac-var 2)
(let ((mac-var 3))
(set! test-mac (macro (x) (set! test-macro2 100)(test::assert-equal 3 mac-var)`(* ,mac-var ,x))))
(set! test-macro1 (test-mac 10))
(test::assert-equal 30 test-macro1)
(test::assert-equal 100 test-macro2)


maybe-docstring? Type: Lambda
root::maybe-docstring? Usage: (maybe-docstring? form)

True if form might be a docstring, nil otherwise.

Example:
(test::assert-true (maybe-docstring? "string"))
(test::assert-true (maybe-docstring? '(str 1 2 3)))
(test::assert-false (maybe-docstring? '(1 2 3)))


meta-add-tags Type: Function
root::meta-add-tags Usage: (meta-add-tags expression tag*)

Adds multiple meta tags to an expression. It will work with symbols or vectors or lists of symbols (or any combination). This is intended for helping with structs and interfaces in lisp, you probably do not want to use it.

Example:
(def meta-add-tags-var '(1 2 3))
(meta-add-tags meta-add-tags-var :tag1)
(test::assert-true (meta-tag? meta-add-tags-var :tag1))
(test::assert-false (meta-tag? meta-add-tags-var :tag2))
(meta-add-tags meta-add-tags-var :tag2 '(:tag3 :tag4) '#(:tag5 :tag6) :tag7)
(test::assert-true (meta-tag? meta-add-tags-var :tag2))
(test::assert-true (meta-tag? meta-add-tags-var :tag3))
(test::assert-true (meta-tag? meta-add-tags-var :tag4))
(test::assert-true (meta-tag? meta-add-tags-var :tag5))
(test::assert-true (meta-tag? meta-add-tags-var :tag6))
(test::assert-true (meta-tag? meta-add-tags-var :tag7))


meta-column-no Type: SpecialForm
root::meta-column-no Usage: (meta-column-no)

Column number from the file this came from.

Example:
;(meta-column-no)
#t


meta-file-name Type: SpecialForm
root::meta-file-name Usage: (meta-file-name)

File name of the file this came from.

Example:
;(meta-file-name)
#t


meta-line-no Type: SpecialForm
root::meta-line-no Usage: (meta-line-no)

Line number from the file this came from.

Example:
;(meta-line-no)
#t


meta-tag? Type: Function
root::meta-tag? Usage: (meta-tag? expression tag)

True if expression has the meta tag ‘tag’ set. This is intended for helping with structs and interfaces in lisp, you probably do not want to use it.

Example:
(def meta-add-tag-var '(1 2 3))
(meta-add-tags meta-add-tag-var :tag1)
(test::assert-true (meta-tag? meta-add-tag-var :tag1))
(test::assert-false (meta-tag? meta-add-tag-var :tag2))


nsubstitute! Type: Lambda
root::nsubstitute! Usage: (nsubstitute! new-item old-item lst &rest mods)

Replaces all instances of old-item in lst with new-item. If last argument passed in is keyword :first only the first instance of old-item will be replaced.

Example:
(let ((lst (list 1 2 3 4 5)))
(test::assert-equal (list 1 2 10 4 5) (nsubstitute! 10 3 lst))
(test::assert-equal (list 1 2 10 4 5) lst))


occurs Type: Lambda
root::occurs Usage: (occurs (list 1 2 ...) 7) (occurs (list 1 2 ...) 0 (fn (x) (% x 2)))

Counts instances of item in sequence. Optional third argument is a function that can be applied to the specific element in the list before equality is tested with item.

Example:
(test::assert-equal 7 (occurs (list 1 3 5 2 4 10 2 4 88 2 1) 0 (fn (x) (% x 2))))
(test::assert-equal 3 (occurs (list 1 3 5 2 4 10 2 4 88 2 1) 2))
(test::assert-equal 0 (occurs (list 1 3 5 2 4 10 2 4 88 2 1) 42))
(test::assert-equal 2 (occurs (list 1 3 5 2 4 10 2 4 88 2 1) 8 (fn (x) (* x 2))))


print Type: Function
root::print Usage: (print arg0 ... argN) -> nil

Print the arguments (as strings) to stdout.

Example:
; Use a file for stdout for test.
(dyn *stdout* (open "/tmp/sl-sh.print.test" :create :truncate) (do (print "Print test out")(print " two") (close *stdout*)))
(test::assert-equal "Print test out two" (read-line (open "/tmp/sl-sh.print.test" :read)))


print-error Type: Lambda
root::print-error Usage: (print-error error)

Prints out an error with a backtrace. Used with the return of get-error when it produces an error

Example:
(let
((print-error-test (get-error (err "Oops!")))
(file-name "$(temp-dir)/print-error.test")
(topen))
(out> file-name (print-error print-error-test))
(set! topen (open file-name :read))
(test::assert-true (> (length (read-line topen)) 5))
(close topen))


println Type: Function
root::println Usage: (println arg0 ... argN) -> nil

Print the arguments (as strings) to stdout and then a newline.

Example:
; Use a file for stdout for test.
(dyn *stdout* (open "/tmp/sl-sh.println.test" :create :truncate) (do (println "Println test out")(println "line two") (close *stdout*)))
(def topen (open "/tmp/sl-sh.println.test" :read))
(test::assert-equal "Println test out
" (read-line topen))
(test::assert-equal "line two
" (read-line topen))


quote Type: SpecialForm
root::quote Usage: 'expression -> expression

Return expression without evaluation. The reader macro ‘expression will expand to (quote expression).

Example:
(test::assert-equal (list 1 2 3) (quote (1 2 3)))
(test::assert-equal (list 1 2 3) '(1 2 3))
(test::assert-equal '(1 2 3) (quote (1 2 3)))


reader-macro-dot Type: Lambda
root::reader-macro-dot Usage: (reader-macro-dot stream ch)

Reader macro for #.(…). Do not call directly.

Example:
(def dot-test (read "(1 2 #.(* 3 10) #.(str "o" "ne"))))
(test::assert-equal '(1 2 30 "one"))


recur Type: Function
root::recur Usage: (recur &rest)

Recursively call the enclosing function with the given parameters. Recur uses tail call optimization and must be in the tail position or it is an error. For a named function it would be equivalent to a normal recursive call in a tail position but it requires a tail position and does not need a name (a normal recursive call would work in a non-tail position but could blow the stack if it is to deep- unlike a recur or tail position recursive call). NOTE: potential footgun, the let macro expands to a lambda (fn) and a recur used inside the let would bind with the let not the enclosing lambda (this would apply to any macro that also expands to a lamda- this is by design with the loop macro but would be unexpected with let).

Example:
(def tot 0)
(loop (idx) (3) (do
(set! tot (+ tot 1))
(if (> idx 1) (recur (- idx 1)))))
(assert-equal 3 tot)
(set! tot 0)
((fn (idx) (do
(set! tot (+ tot 1))
(if (> idx 1) (recur (- idx 1)))))5)
(assert-equal 5 tot)


ref Type: SpecialForm
root::ref Usage: (ref symbol) -> expression

Return the expression that is referenced by symbol. Symbol is only evaluated if a list (that produces a symbol) and must be bound in the current scope or an error is raised.

Example:
(def test-is-def #t)
(def test-is-def2 'test-is-def)
(test::assert-true (ref test-is-def))
(set! test-is-def '(1 2 3))
(test::assert-equal '(1 2 3) (ref test-is-def))
(test::assert-error (ref test-is-def-no-exist))
(test::assert-error (ref (ref test-is-def)))
(test::assert-equal '(1 2 3) (ref (ref test-is-def2)))


return-from Type: SpecialForm
root::return-from Usage: (return-from name expression?)

Causes enclosing block with name (name is not evaluated) to evaluate to expression.

Example:
(test::assert-equal '(4 5) (block xxx '(1 2) (return-from xxx '(4 5)) '(a b) '(2 3)))
(test::assert-equal '(4 5) (block xxx '(1 2) (return-from nil '(4 5)) '(a b) '(2 3)))
(test::assert-equal '(5 6) (block xxx '(1 2) (block yyy (return-from xxx '(5 6)) '(a b)) '(2 3)))
(test::assert-equal '(5 6) (block xxx '(1 2) (block yyy ((fn (p) (return-from xxx p)) '(5 6)) '(a b)) '(2 3)))
(test::assert-equal '(2 3) (block xxx '(1 2) (block yyy (return-from yyy #t) '(a b)) '(2 3)))


set! Type: SpecialForm
root::set! Usage: (set! symbol expression) -> expression

Sets an existing expression in the current scope(s). Return the expression that was set. Symbol is not evaluted. Set will set the first binding it finds starting in the current scope and then trying enclosing scopes until exhausted.

Example:
(def test-do-one nil)
(def test-do-two nil)
(def test-do-three (do (set! test-do-one "One")(set! test-do-two "Two")"Three"))
(test::assert-equal "One" test-do-one)
(test::assert-equal "Two" test-do-two)
(test::assert-equal "Three" test-do-three)
(let ((test-do-one nil))
; set the currently scoped value.
(test::assert-equal "1111" (set! test-do-one "1111"))
(test::assert-equal "1111" test-do-one))
; Original outer scope not changed.
(test::assert-equal "One" test-do-one)
;(set! (sym "test-do-one") "do one")
;(test::assert-equal "do one" test-do-one)
(test::assert-error (set! (sym->str test-do-one) "do one 2"))


substitute Type: Macro
root::substitute Usage: (substitute new-item old-item lst &rest mods)

Replaces all instances of old-item in copy of lst with new-item. If last argument passed in is keyword :first only the first instance of old-item will be replaced.

Example:
(let ((lst (list 1 2 3 4 5))
(lst2 (list 1 2 3 3 3 4 5)))
(test::assert-equal (list 1 2 10 4 5) (substitute 10 3 lst))
(test::assert-equal lst lst)
(test::assert-equal (list 1 2 4 4 4 4 5) (substitute 4 3 lst2))
(test::assert-equal (list 1 2 4 3 3 4 5) (substitute 4 3 lst2 :first)))


undef Type: SpecialForm
root::undef Usage: (undef symbol) -> expression

Remove a symbol from the current namespace (if it exists). Returns the expression that was removed. It is an error if symbol is not defined in the current namespace. Symbol is not evaluted.

Example:
(def test-undef nil)
(test::assert-true (def? test-undef))
(undef test-undef)
(test::assert-false (def? test-undef))
(def test-undef "undef")
(test::assert-equal "undef" (undef test-undef))
(test::assert-false (def? test-undef))
(test::assert-equal "undef: symbol test-undef not defined in current scope (can only undef symbols in current scope)." (cadr (get-error (undef test-undef))))


unwind-protect Type: Function
root::unwind-protect Usage: (unwind-protect protected cleanup*) -> [protected result]

After evaluation first form, make sure the following cleanup forms run (returns first form’s result).

Example:
(def test-unwind-one nil)
(def test-unwind-err (get-error
(unwind-protect (err "Some protected error") (set! test-unwind-one "got it"))))
(test::assert-equal :error (car test-unwind-err))
(test::assert-equal "Some protected error" (cadr test-unwind-err))
(test::assert-equal "got it" test-unwind-one)
(def test-unwind-one nil)
(def test-unwind-two nil)
(def test-unwind-three nil)
(def test-unwind-four nil)
(def test-unwind-err (get-error
(unwind-protect
(do (set! test-unwind-one "set one")(err "Some protected error two")(set! test-unwind-two "set two"))
(set! test-unwind-three "set three")(set! test-unwind-four "set four"))))
(test::assert-equal :error (car test-unwind-err))
(test::assert-equal "Some protected error two" (cadr test-unwind-err))
(test::assert-equal "set one" test-unwind-one)
(test::assert-equal nil test-unwind-two)
(test::assert-equal "set three" test-unwind-three)
(test::assert-equal "set four" test-unwind-four)


values Type: Function
root::values Usage: (values expression*)

Produces a multi values object. Useful for returning more then one value from a function when most of time you only care about the first (primary) item. When evaluting a muti values object it will evaluate as if it the first item only.

Example:
(test::assert-true (values? (values 1 "str" 5.5)))
(test::assert-equal 1 (values-nth 0 (values 1 "str" 5.5)))
(test::assert-equal "str" (values-nth 1 (values 1 "str" 5.5)))
(test::assert-equal 5.5 (values-nth 2 (values 1 "str" 5.5)))


values-length Type: Function
root::values-length Usage: (values-length expression)

If expression is a values object then return it’s length (number of values).

Example:
(test::assert-equal 3 (values-length (values 1 "str" 5.5)))
(test::assert-equal 2 (values-length (values 1 "str")))
(test::assert-equal 1 (values-length (values "str")))
(test::assert-equal 0 (values-length (values)))
(test::assert-equal "str" (values-nth 1 (values 1 "str" 5.5)))
(test::assert-equal 5.5 (values-nth 2 (values 1 "str" 5.5)))
(def test-vals-len (values 1 "str" 5.5))
(test::assert-equal 3 (values-length test-vals-len))


values-nth Type: Function
root::values-nth Usage: (values-nth idx expression)

If expression is a values object then return the item at index idx.

Example:
(test::assert-equal 1 (values-nth 0 (values 1 "str" 5.5)))
(test::assert-equal "str" (values-nth 1 (values 1 "str" 5.5)))
(test::assert-equal 5.5 (values-nth 2 (values 1 "str" 5.5)))
(def test-vals-nth (values 1 "str" 5.5))
(test::assert-equal 1 (values-nth 0 test-vals-nth))
(test::assert-equal "str" (values-nth 1 test-vals-nth))
(test::assert-equal 5.5 (values-nth 2 test-vals-nth))


var Type: SpecialForm
root::var Usage: (var symbol expression) -> expression

NOTE: var is deprecated, use let or let* to create local bindings. Adds an expression to the current lexical scope. Return the expression that was defined. This will not add to a namespace (use def for that), use it within functions or let forms to create local bindings. Symbol is not evaluated.

Example:
(let (())
(var test-do-one nil)
(var test-do-two nil)
(var test-do-three (do (set! test-do-one "One")(set! test-do-two "Two")"Three"))
(test::assert-equal "One" test-do-one)
(test::assert-equal "Two" test-do-two)
(test::assert-equal "Three" test-do-three)
(let ((test-do-one nil))
; Add this to the let's scope (shadow the outer test-do-two).
(test::assert-equal "Default" (var test-do-two "Default"))
; set the currently scoped value.
(set! test-do-one "1111")
(set! test-do-two "2222")
(test::assert-equal "1111" test-do-one)
(test::assert-equal "2222" test-do-two))
; Original outer scope not changed.
(test::assert-equal "One" test-do-one)
(test::assert-equal "Two" test-do-two))


File forms

Options to open, one or more of these can be added to open after the filename. A file can only be opened for reading or writing (read is default).

Option Description
:read Open file for reading, this is the default.
:write Open file for writing.
:append Open file for writing and append new data to end.
:truncate Open file for write and delete all existing data.
:create Create the file if it does not exist and open for writing.
:create-new Create if does not exist, error if it does and open for writing.
:on-error-nil If open has an error then return nil instead of producing an error.

Notes on closing. Files will close when they go out of scope. Using close will cause a reference to a file to be marked close (removes that reference). If there are more then one references to a file it will not actually close until all are released. Close will also flush the file even if it is not the final reference. If a reference to a file is captured in a closure that can also keep it open (closures currently capture the entire scope not just used symbols).

cd Type: Function
root::cd Usage: (cd dir-to-change-to)

Change directory.

Example:
(syscall 'mkdir "/tmp/tst-fs-cd")
(syscall 'touch "/tmp/tst-fs-cd/fs-cd-marker")
(test::assert-false (fs-exists? "fs-cd-marker"))
(pushd "/tmp/tst-fs-cd")
(root::cd "/tmp")
(root::cd "/tmp/tst-fs-cd")
(test::assert-true (fs-exists? "fs-cd-marker"))
(syscall 'rm "/tmp/tst-fs-cd/fs-cd-marker")
(popd)
(syscall 'rmdir "/tmp/tst-fs-cd")


close Type: Function
root::close Usage: (close file)

Close a file.

Example:
(def tmp (get-temp))
(def tst-file (open (str tmp "/slsh-tst-open.txt") :create :truncate))
(write-line tst-file "Test Line Two")
(close tst-file)
(def tst-file (open (str tmp "/slsh-tst-open.txt") :read))
(test::assert-equal "Test Line Two
" (read-line tst-file))
(close tst-file)


collate-fs-changes Type: Lambda
root::collate-fs-changes Usage: (collate-fs-changes file-or-dir-to-watch)

Takes a file or directory to watch and returns a function that encloses the state of the file or directory (and all its contents). When the resultant function is called it returns a map whose keys are the types of change: :created , :deleted, and :modified and values are vectors of files subject to the change. Each invocation encloses the state of the previous invocation and can be called at any time to report change sets since the last invocation. sample return value: (make-hash ((:modified . #(“/tmp/collate-fs-changes”)) (:deleted . #()) (:created . #(“/tmp/collate-fs-changes/foo1.txt”))))

Example:
(defn test-collate (collate-test-dir)
(let* ((collate-test-file0 (get-temp-file collate-test-dir))
(collator (collate-fs-changes collate-test-dir))
(collate-test-file1 (get-temp-file collate-test-dir))
(slp (sleep 100))
(changes (collator)))
(test::assert-equal (vec collate-test-file1) (hash-get changes :created))
(test::assert-equal (make-vec) (hash-get changes :deleted))
(let ((tst-file (open collate-test-file0 :truncate)))
(write-string tst-file "boop")
(flush tst-file)
(close tst-file))
(sleep 100)
(set! changes (collator))
(test::assert-equal (vec collate-test-file0) (hash-get changes :modified))
(test::assert-equal (make-vec) (hash-get changes :deleted))
(test::assert-equal (make-vec) (hash-get changes :created))
(fs-rm collate-test-dir)
(sleep 100)
(set! changes (collator))
(test::assert-equal (make-vec) (hash-get changes :created))
(test::assert-equal (make-vec) (hash-get changes :modified))
(let ((del-items (hash-get changes :deleted)))
(test::assert-equal 3 (length del-items))
(test::assert-includes collate-test-dir del-items)
(test::assert-includes collate-test-file0 del-items)
(test::assert-includes collate-test-file1 del-items))))
(with-temp (fn (tmp-dir)
(let ((a-dir (get-temp tmp-dir)))
(test-collate a-dir))))


flush Type: Function
root::flush Usage: (flush file)

Flush a file.

Example:
(def tmp (get-temp))
(def tst-file (open (str tmp \"/slsh-tst-open.txt\") :create :truncate))
(write-line tst-file \"Test Line Three\")
(flush tst-file)
(def tst-file (open (str tmp \"/slsh-tst-open.txt\") :read))
(test::assert-equal \"Test Line Three\n\" (read-line tst-file))
(close tst-file)


fs-accessed Type: Function
root::fs-accessed Usage: (fs-accessed /path/to/file/or/dir)

Returns the unix time file last accessed in ms.

Example:
(with-temp-file (fn (tmp)
(let ((tst-file (open tmp :read))
(last-acc (fs-accessed tmp)))
(close tst-file)
(let ((tst-file (open tmp :read)))
(test::assert-true (> (fs-accessed tmp) last-acc))
(close tst-file))))


fs-base Type: Function
root::fs-base Usage: (fs-base /path/to/file/or/dir)

Returns base name of file or directory passed to function.

Example:
(with-temp (fn (tmp)
(let ((tmp-file (temp-file tmp)))
(test::assert-equal (length \".tmp01234\") (length (fs-base tmp-file))))))


fs-crawl Type: Function
root::fs-crawl Usage: (fs-crawl /path/to/file/or/dir (fn (x) (println "found path" x) [max-depth]

[:follow-syms]) If a directory is provided the path is recursively searched and every file and directory is called as an argument to the provided function. If a file is provided the path is provided as an argument to the provided function. Takes two optional arguments (in any order) an integer, representing max depth to traverse if file is a directory, or the symbol, :follow-syms, to follow symbol links when traversing if desired.

Example:
(with-temp-file (fn (tmp-file)
(def cnt 0)
(fs-crawl tmp-file (fn (x)
(test::assert-equal (fs-base tmp-file) (fs-base x))
(set! cnt (+ 1 cnt))))
(test::assert-equal 1 cnt)))
(defn create-in (in-dir num-files visited)
(dotimes-i i num-files
(hash-set! visited (get-temp-file in-dir) nil)))
(defn create-dir (tmp-dir visited)
(let ((new-tmp (get-temp tmp-dir)))
(hash-set! visited new-tmp nil)
new-tmp))
(with-temp (fn (root-tmp-dir)
(let ((tmp-file-count 5)
(visited (make-hash)))
(def cnt 0)
(hash-set! visited root-tmp-dir nil)
(create-in root-tmp-dir tmp-file-count visited)
(let* ((tmp-dir (create-dir root-tmp-dir visited))
(new-files (create-in tmp-dir tmp-file-count visited))
(tmp-dir (create-dir tmp-dir visited))
(new-files (create-in tmp-dir tmp-file-count visited)))
(fs-crawl root-tmp-dir (fn (x)
(let ((file (hash-get visited x)))
(test::assert-true (not file)) ;; also tests double counting
(hash-set! visited x #t)
(set! cnt (+ 1 cnt)))))
(test::assert-equal (+ 3 (* 3 tmp-file-count)) cnt)
(test::assert-equal (+ 3 (* 3 tmp-file-count)) (length (hash-keys visited)))
(iterator::map (fn (x) (test::assert-true (hash-get visited y))) (hash-keys visited))))))
(with-temp (fn (root-tmp-dir)
(let ((tmp-file-count 5)
(visited (make-hash)))
(def cnt 0)
(hash-set! visited root-tmp-dir nil)
(create-in root-tmp-dir tmp-file-count visited)
(let* ((tmp-dir (create-dir root-tmp-dir visited))
(new-files (create-in tmp-dir tmp-file-count visited))
(tmp-dir (create-dir tmp-dir (make-hash)))
(new-files (create-in tmp-dir tmp-file-count (make-hash))))
(fs-crawl root-tmp-dir (fn (x)
(let ((file (hash-get visited x)))
(test::assert-true (not file)) ;; also tests double counting
(hash-set! visited x #t)
(set! cnt (+ 1 cnt)))) 2)
(test::assert-equal (+ 3 (* 2 tmp-file-count)) cnt)
(test::assert-equal (+ 3 (* 2 tmp-file-count)) (length (hash-keys visited)))
(iterator::map (fn (x) (test::assert-true (hash-get visited y))) (hash-keys visited))))))
(with-temp (fn (root-tmp-dir)
(let ((tmp-file-count 5)
(visited (make-hash)))
(def cnt 0)
(hash-set! visited root-tmp-dir nil)
(create-in root-tmp-dir tmp-file-count visited)
(let* ((tmp-dir (create-dir root-tmp-dir (make-hash)))
(new-files (create-in tmp-dir tmp-file-count (make-hash)))
(tmp-dir (create-dir tmp-dir (make-hash)))
(new-files (create-in tmp-dir tmp-file-count (make-hash))))
(fs-crawl root-tmp-dir (fn (x)
(let ((file (hash-get visited x)))
(test::assert-true (not file)) ;; also tests double counting
(hash-set! visited x #t)
(set! cnt (+ 1 cnt)))) 1)
(test::assert-equal (+ 2 tmp-file-count) cnt)
(test::assert-equal (+ 2 tmp-file-count) (length (hash-keys visited)))
(iterator::map (fn (x) (test::assert-true (hash-get visited y))) (hash-keys visited))))))


fs-dir? Type: Function
root::fs-dir? Usage: (fs-dir? path-to-test)

Is the given path a directory?

Example:
$(mkdir /tmp/tst-fs-dir)
$(touch /tmp/tst-fs-dir/fs-dir-file)
(test::assert-false (fs-dir? "/tmp/tst-fs-dir/fs-dir-file"))
(test::assert-true (fs-dir? "/tmp/tst-fs-dir"))
(test::assert-false (fs-dir? "/tmp/tst-fs-dir/fs-dir-nope"))
$(rm /tmp/tst-fs-dir/fs-dir-file)
$(rmdir /tmp/tst-fs-dir)


fs-exists? Type: Function
root::fs-exists? Usage: (fs-exists? path-to-test)

Does the given path exist?

Example:
$(mkdir /tmp/tst-fs-exists)
$(touch /tmp/tst-fs-exists/fs-exists)
(test::assert-true (fs-exists? "/tmp/tst-fs-exists/fs-exists"))
(test::assert-true (fs-exists? "/tmp/tst-fs-exists"))
(test::assert-false (fs-exists? "/tmp/tst-fs-exists/fs-exists-nope"))
$(rm /tmp/tst-fs-exists/fs-exists)
$(rmdir /tmp/tst-fs-exists)


fs-file? Type: Function
root::fs-file? Usage: (fs-file? path-to-test)

Is the given path a file?

Example:
$(mkdir /tmp/tst-fs-file)
$(touch "/tmp/tst-fs-file/fs-file")
(test::assert-true (fs-file? "/tmp/tst-fs-file/fs-file"))
(test::assert-false (fs-file? "/tmp/tst-fs-file"))
(test::assert-false (fs-file? "/tmp/tst-fs-file/fs-file-nope"))
$(rm "/tmp/tst-fs-file/fs-file")
$(rmdir /tmp/tst-fs-file)


fs-len Type: Function
root::fs-len Usage: (fs-len /path/to/file/or/dir)

Returns the size of the file in bytes.

Example:
(with-temp-file (fn (tmp)
(let ((tst-file (open tmp :create :truncate)))
(write-line tst-file \"Test Line Read Line One\")
(write-string tst-file \"Test Line Read Line Two\")
(flush tst-file)
(close tst-file)
(println \"fs-len is: \" (fs-len tst-file))
(test::assert-equal 47 (fs-len tst-file)))))


fs-modified Type: Function
root::fs-modified Usage: (fs-modified /path/to/file/or/dir)

Returns the unix time file last modified in ms.

Example:
(with-temp-file (fn (tmp)
(let ((tst-file (open tmp :create :truncate))
(last-mod (fs-modified tmp)))
(write-line tst-file \"Test Line Read Line One\")
(write-string tst-file \"Test Line Read Line Two\")
(flush tst-file)
(close tst-file)
(test::assert-true (> (fs-modified tmp) last-mod)))))


fs-notify Type: Lambda
root::fs-notify Usage: (fs-notify callback to-watch &rest args)

fs-notify is designed to notify the caller of changes to a file or directory heirarchy via a callback that accepts two arguments, the file that changed and the type of change: :created, :deleted, xor :modified. Takes a callback and file or directory to watch for changes and the number of milliseconds to sleep before checking for changes to the provided file/directory hierarchy. This function loops forever, and calls the callback whenever it detects a change. This function relies on the function collate-fs-changes to compute differences. The following invocation of fs-notify prints out every change event for the provided directory, polling every 250ms by default. (fs-notify (fn (f e) (println “file: “ f “, event: “ e)) “/dir/to/watch”) This incovation provides an optional arg to specify the polling rate in ms. (fs-notify (fn (f e) (println “file: “ f “, event: “ e)) “/dir/to/watch” 1000)

Example:
#t


fs-parent Type: Function
root::fs-parent Usage: (fs-parent /path/to/file/or/dir)

Returns base name of file or directory passed to function.

Example:
(with-temp (fn (tmp)
(let ((tmp-file (get-temp-file tmp)))
(test::assert-true (fs-same? (fs-parent tmp-file) tmp)))))


fs-rm Type: Function
root::fs-rm Usage: (fs-rm \"/dir/or/file/to/remove\")

Takes a file or directory as a string and removes it. Works recursively for directories.

Example:
(def fp nil)
(let* ((a-file (get-temp-file)))
(test::assert-true (fs-exists? a-file))
(set! fp a-file)
(fs-rm a-file)))
(test::assert-false (nil? fp))
(test::assert-false (fs-exists? fp))


fs-same? Type: Function
root::fs-same? Usage: (fs-same? /path/to/file/or/dir /path/to/file/or/dir)

Returns true if the two provided file paths refer to the same file or directory.

Example:
(with-temp-file (fn (tmp-file)
(test::assert-true (fs-same? tmp-file tmp-file)))


get-temp Type: Function
root::get-temp Usage: (get-temp [\"/path/to/directory/to/use/as/base\" \"optional-prefix\" \"optional-suffix\" length])

Creates a directory inside of an OS specific temporary directory. See temp-dir for OS specific notes. Also accepts an optional prefix, an optional suffix, and an optional length for the random number of characters in the temporary file created. Defaults to prefix of ".tmp", no suffix, and five random characters.

Example:
(test::assert-true (str-contains (temp-dir) (get-temp)))
(with-temp (fn (tmp)
(let ((tmp-dir (get-temp tmp)))
(test::assert-true (str-contains tmp tmp-dir)))))
(with-temp (fn (tmp)
(let ((tmp-dir (get-temp tmp \"some-prefix\")))
(test::assert-true (str-contains tmp tmp-dir))
(test::assert-true (str-contains \"some-prefix\" tmp-dir)))))
(with-temp (fn (tmp)
(let ((tmp-dir (get-temp tmp \"some-prefix\" \"some-suffix\")))
(test::assert-true (str-contains tmp tmp-dir))
(test::assert-true (str-contains \"some-prefix\" tmp-dir))
(test::assert-true (str-contains \"some-suffix\" tmp-dir)))))
(with-temp (fn (tmp)
(let ((tmp-dir (get-temp tmp \"some-prefix\" \"some-suffix\" 6)))
(test::assert-true (str-contains tmp tmp-dir))
(test::assert-true (str-contains \"some-prefix\" tmp-dir))
(test::assert-true (str-contains \"some-suffix\" tmp-dir))
(test::assert-equal (length \"some-prefix012345some-suffix\") (length (fs-base tmp-dir))))))


get-temp-file Type: Function
root::get-temp-file Usage: (get-temp-file [\"/path/to/directory/to/use/as/base\" \"optional-prefix\" \"optional-suffix\" length])

Returns name of file created inside temporary directory. Optionally takes a directory to use as the parent directory of the temporary file. Also accepts an optional prefix, an optional suffix, and an optional length for the random number of characters in the temporary files created. Defaults to prefix of ".tmp", no suffix, and five random characters.

Example:
(test::assert-true (str-contains (temp-dir) (get-temp-file)))
(with-temp (fn (tmp)
(let ((tmp-file (get-temp-file tmp)))
(test::assert-true (str-contains tmp tmp-file)))))
(with-temp (fn (tmp)
(let ((tmp-file (get-temp-file tmp \"some-prefix\")))
(test::assert-true (str-contains \"some-prefix\" tmp-file)))))
(with-temp (fn (tmp)
(let ((tmp-file (get-temp-file tmp \"some-prefix\" \"some-suffix\")))
(test::assert-true (str-contains \"some-prefix\" tmp-file))
(test::assert-true (str-contains \"some-suffix\" tmp-file)))))
(with-temp (fn (tmp)
(let ((tmp-file (get-temp-file tmp \"some-prefix\" \"some-suffix\" 10)))
(test::assert-true (str-contains \"some-prefix\" tmp-file))
(test::assert-true (str-contains \"some-suffix\" tmp-file))
(test::assert-equal (length \"some-prefix0123456789some-suffix\") (length (fs-base tmp-file))))))


glob Type: Function
root::glob Usage: (glob /path/with/*)

Takes a list/varargs of globs and return the list of them expanded.

Example:
(syscall 'mkdir "/tmp/tst-fs-glob")
(syscall 'touch "/tmp/tst-fs-glob/g1")
(syscall 'touch "/tmp/tst-fs-glob/g2")
(syscall 'touch "/tmp/tst-fs-glob/g3")
(test::assert-equal '("/tmp/tst-fs-glob/g1" "/tmp/tst-fs-glob/g2" "/tmp/tst-fs-glob/g3") (glob "/tmp/tst-fs-glob/*"))
(syscall 'rm "/tmp/tst-fs-glob/g1")
(syscall 'rm "/tmp/tst-fs-glob/g2")
(syscall 'rm "/tmp/tst-fs-glob/g3")
(syscall 'rmdir "/tmp/tst-fs-glob")


open Type: Function
root::open Usage: (open filename option*)

Open a file. Options are: :read :write :append :truncate :create :create-new :on-error-nil

Example:
(def tmp (get-temp))
(def test-open-f (open (str tmp "/slsh-tst-open.txt") :create :truncate))
(write-line test-open-f "Test Line One")
(close test-open-f)
(test::assert-equal "Test Line One
" (read-line (open (str tmp "/slsh-tst-open.txt"))))


read Type: Function
root::read Usage: (read [file\|string]? end-exp?) -> expression

Read a file or string and return the next object (symbol, string, list, etc). Raises an error if the file or string has been read unless end-exp is provided then returns that on the end condition. If no parameters are provided then read stdin.

Example:
(def tmp (get-temp))
(def tst-file (open (str tmp "/slsh-tst-open.txt") :create :truncate))
(write-line tst-file "(1 2 3)(x y z)")
;(write-string tst-file "Test Line Read Line Two")
(flush tst-file)
(def tst-file (open (str tmp "/slsh-tst-open.txt") :read))
(test::assert-equal '(1 2 3) (read tst-file))
(test::assert-equal '(x y z) (read tst-file))
(test::assert-error (read test-file))
(close tst-file)
(def tst-file (open (str tmp "/slsh-tst-open.txt") :read))
(test::assert-equal '(1 2 3) (read tst-file :done))
(test::assert-equal '(x y z) (read tst-file :done))
(test::assert-equal :done (read tst-file :done))
(close tst-file)
(test::assert-equal '(4 5 6) (read "(4 5 6)"))
(def test-str "7 8 9")
(test::assert-equal 7 (read test-str))
(test::assert-equal 8 (read test-str))
(test::assert-equal 9 (read test-str))
(test::assert-error (read test-str))
(def test-str "7 8 9")
(test::assert-equal 7 (read test-str :done))
(test::assert-equal 8 (read test-str :done))
(test::assert-equal 9 (read test-str :done))
(test::assert-equal :done (read test-str :done))
(test::assert-equal '(x y z) (read "(x y z)"))


read-all Type: Function
root::read-all Usage: (read-all [file\|string]? empty-exp?) -> list\|vec\|empty-exp

Read a file or string and return the list representation. This reads the entire file or string and will wrap in an outer vector if not a vector or list (always returns a vector or list). Unlike most lisp readers this one will put loose symbols in a list (i.e. you enter things at the repl without the enclosing parens). Note the file|string arg is optional, if not provided will read from stdin (or can provide stdin). If the read item is empty (including a comment) then raises an error or produces empty-exp if it is provided.

Example:
(def tmp (get-temp))
(def tst-file (open (str tmp "/slsh-tst-open.txt") :create :truncate))
(write-line tst-file "(1 2 3)(x y z)")
(flush tst-file)
(def tst-file (open (str tmp "/slsh-tst-open.txt") :read))
(test::assert-equal '#((1 2 3)(x y z)) (read-all tst-file))
(close tst-file)
(test::assert-equal '(4 5 6) (read-all "(4 5 6)"))
(test::assert-equal '(7 8 9) (read-all "7 8 9"))
(test::assert-equal '(x y z) (read-all "(x y z)" :not-used))
(test::assert-equal :empty (read-all ";(x y z)" :empty))


read-line Type: Function
root::read-line Usage: (read-line file) -> string

Read a line from a file.

Example:
(def tmp (get-temp))
(def tst-file (open (str tmp "slsh-tst-open.txt") :create :truncate))
(write-line tst-file "Test Line Read Line One")
(write-string tst-file "Test Line Read Line Two")
(flush tst-file)
(def tst-file (open (str tmp "slsh-tst-open.txt") :read))
(test::assert-equal "Test Line Read Line One
" (read-line tst-file))
(test::assert-equal "Test Line Read Line Two" (read-line tst-file))
(close tst-file)


temp-dir Type: Function
root::temp-dir Usage: (temp-dir)

Returns a string representing the temporary directory. See get-temp for higher level temporary directory creation mechanism. On Unix: Returns the value of the TMPDIR environment variable if it is set, otherwise for non-Android it returns /tmp. If Android, since there is no global temporary folder (it is usually allocated per-app), it returns /data/local/tmp. On Windows: Returns the value of, in order, the TMP, TEMP, USERPROFILE environment variable if any are set and not the empty string. Otherwise, temp_dir returns the path of the Windows directory. This behavior is identical to that of GetTempPath, which this function uses internally.

Example:
(test::assert-true (fs-dir? (temp-dir)))


with-temp Type: Function
root::with-temp Usage: (with-temp (fn (x) (println \"given temp dir:\" x)) [\"optional-prefix\" \"optional-suffix\" length])

Takes a function that accepts a temporary directory. This directory will be recursively removed when the provided function is finished executing. Also accepts an optional prefix, an optional suffix, and an optional length for the random number of characters in the temporary directory created. Defaults to prefix of ".tmp", no suffix, and five random characters.

Example:
(def fp nil)
(with-temp (fn (tmp-dir)
(let* ((tmp-file (str tmp-dir \"/sl-sh-tmp-file.txt\"))
(a-file (open tmp-file :create :truncate)))
(test::assert-true (fs-exists? tmp-file))
(set! fp tmp-file)
(close a-file))))
(test::assert-false (nil? fp))
(test::assert-false (fs-exists? fp))
(with-temp
(fn (tmp)
(test::assert-true (str-contains \"some-prefix\" tmp)))
\"some-prefix\")
(with-temp
(fn (tmp)
(test::assert-true (str-contains \"some-prefix\" tmp))
(test::assert-true (str-contains \"some-suffix\" tmp)))
\"some-prefix\"
\"some-suffix\")
(with-temp
(fn (tmp)
(test::assert-true (str-contains \"some-prefix\" tmp))
(test::assert-true (str-contains \"some-suffix\" tmp))
(test::assert-equal (length \"some-prefix0123456789some-suffix\") (length (fs-base tmp))))
\"some-prefix\"
\"some-suffix\"
10)


with-temp-file Type: Function
root::with-temp-file Usage: (with-temp-file (fn (x) (println \"given temp file:\" x)) [\"optional-prefix\" \"optional-suffix\" length])

Takes a function that accepts a temporary file. This file will be removed when the provided function is finished executing. Also accepts an optional prefix, an optional suffix, and an optional length for the random number of characters in the temporary file created. Defaults to prefix of ".tmp", no suffix, and five random characters.

Example:
(def fp nil)
(with-temp-file (fn (tmp-file)
(let* ((a-file (open tmp-file :create :truncate)))
(test::assert-true (fs-exists? tmp-file))
(set! fp tmp-file)
(close a-file))))
(test::assert-false (nil? fp))
(test::assert-false (fs-exists? fp))
(with-temp-file
(fn (tmp)
(test::assert-true (str-contains \"some-prefix\" tmp)))
\"some-prefix\")
(with-temp-file
(fn (tmp)
(test::assert-true (str-contains \"some-prefix\" tmp))
(test::assert-true (str-contains \"some-suffix\" tmp)))
\"some-prefix\"
\"some-suffix\")
(with-temp-file
(fn (tmp)
(test::assert-true (str-contains \"some-prefix\" tmp))
(test::assert-true (str-contains \"some-suffix\" tmp))
(test::assert-equal (length \"some-prefix0123456789some-suffix\") (length (fs-base tmp))))
\"some-prefix\"
\"some-suffix\"
10)


write-line Type: Function
root::write-line Usage: (write-line file string)

Write a line to a file.

Example:
(def tmp (get-temp))
(def tst-file (open (str tmp "/slsh-tst-open.txt") :create :truncate))
(write-line tst-file "Test Line Write Line")
(flush tst-file)
(def tst-file (open (str tmp "/slsh-tst-open.txt") :read))
(test::assert-equal "Test Line Write Line
" (read-line tst-file))
(close tst-file)


write-string Type: Function
root::write-string Usage: (write-string file string)

Write a string to a file.

Example:
(def tmp (get-temp))
(def tst-file (open (str tmp "/slsh-tst-open.txt") :create :truncate))
(write-string tst-file "Test Line Write Line")
(flush tst-file)
(def tst-file (open (str tmp "/slsh-tst-open.txt") :read))
(test::assert-equal "Test Line Write Line" (read-line tst-file))
(close tst-file)


Globals forms

In sl-sh global symbols (made by ‘def) are wrapped in earmuffs like in common lisp. Some of these symbols contain information used by the standard library and may be useful to end users, while others are intended for use in scripting.

*last-command* Type: String
root::*last-command*  

Namespace: root last run command by sl-sh on repl

*last-status* Type: Int
root::*last-status*  

Namespace: root Return code of last run sl-sh command on the repl

*repl-settings* Type: HashMap
root::*repl-settings*  

Namespace: root hash map of repl settings

*std-lib-namespaces* Type: Vector
root::*std-lib-namespaces*  

Namespace: root vector of all namespaces present in sl-sh by default

*std-lib-syms-hash* Type: HashMap
root::*std-lib-syms-hash*  

Namespace: root vector of all symbols in sl-sh-standard library

Hashmap forms

hash-clear! Type: Function
root::hash-clear! Usage: (hash-clear! hashmap)

Clears a hashmap. This is a destructive form!

Example:
(def tst-hash (make-hash '((:key1 . \"val one\")(key2 . \"val two\")(\"key3\" . \"val three\")(#\\S . \"val S\"))))
(test::assert-equal 4 (length (hash-keys tst-hash)))
(test::assert-true (hash-haskey tst-hash :key1))
(test::assert-true (hash-haskey tst-hash 'key2))
(test::assert-true (hash-haskey tst-hash \"key3\"))
(test::assert-true (hash-haskey tst-hash #\\S))
(hash-clear! tst-hash)
(test::assert-equal 0 (length (hash-keys tst-hash)))
(test::assert-false (hash-haskey tst-hash :key1))
(test::assert-false (hash-haskey tst-hash 'key2))
(test::assert-false (hash-haskey tst-hash \"key3\"))
(test::assert-false (hash-haskey tst-hash #\\S))


hash-get Type: SpecialForm
root::hash-get Usage: (hash-get hashmap key default?) -> value

Get a value for a key from a hashmap. If the optional default is provided and the key is not in the hash then evaluate and return it. NOTE: default will only be evaluted if it is used.

Example:
(def tst-hash (make-hash '((:key1 . "val one")(key2 . "val two")("key3" . "val three")(#\S . "val S"))))
(test::assert-equal 4 (length (hash-keys tst-hash)))
(test::assert-equal "val one" (hash-get tst-hash :key1))
(test::assert-equal "val two" (hash-get tst-hash 'key2))
(test::assert-equal "val three" (hash-get tst-hash "key3"))
(test::assert-equal "val S" (hash-get tst-hash #\S))
(test::assert-equal "default" (hash-get tst-hash :not-here "default"))
(test::assert-equal "string default" (hash-get tst-hash :not-here (str "string " "default")))


hash-haskey Type: Function
root::hash-haskey Usage: (hash-haskey hashmap key)

Checks if a key is in a hashmap.

Example:
(def tst-hash (make-hash '((:key1 . \"val one\")(key2 . \"val two\")(\"key3\" . \"val three\")(#\\S . \"val S\"))))
(test::assert-equal 4 (length (hash-keys tst-hash)))
(test::assert-true (hash-haskey tst-hash :key1))
(test::assert-true (hash-haskey tst-hash 'key2))
(test::assert-true (hash-haskey tst-hash \"key3\"))
(test::assert-true (hash-haskey tst-hash #\\S))
(test::assert-false (hash-haskey tst-hash 'key1))
(test::assert-false (hash-haskey tst-hash :key2))
(test::assert-false (hash-haskey tst-hash \"keynone\"))
(hash-remove! tst-hash :key1)
(test::assert-false (hash-haskey tst-hash :key1))
(hash-set! tst-hash :key1 \"val one b\")
(test::assert-true (hash-haskey tst-hash :key1))


hash-keys Type: Function
root::hash-keys Usage: (hash-keys hashmap)

Returns a vector of all the hashmaps keys. The keys will be unordered.

Example:
(def tst-hash (make-hash '((:key1 . \"val one\")(key2 . \"val two\")(\"key3\" . \"val three\")(#\\S . \"val S\"))))
(test::assert-equal 4 (length (hash-keys tst-hash)))
(test::assert-true (in? (hash-keys tst-hash) :key1) \" Test :key1\")
(test::assert-true (in? (hash-keys tst-hash) 'key2) \" Test key2\")
; Note string or char used as a key will be a symbol in the hash-keys list...
(test::assert-true (in? (hash-keys tst-hash) 'S) \" Test S\")
(test::assert-true (in? (hash-keys tst-hash) 'key3) \" Test key3\")
(test::assert-false (in? (hash-keys tst-hash) :key4))


hash-remove! Type: Function
root::hash-remove! Usage: (hash-remove! hashmap key)

Remove a key from a hashmap. This is a destructive form!

Example:
(def tst-hash (make-hash '((:key1 . \"val one\")(key2 . \"val two\")(\"key3\" . \"val three\")(#\\S . \"val S\"))))
(test::assert-equal 4 (length (hash-keys tst-hash)))
(test::assert-equal \"val one\" (hash-get tst-hash :key1))
(test::assert-equal \"val two\" (hash-get tst-hash 'key2))
(test::assert-equal \"val three\" (hash-get tst-hash \"key3\"))
(test::assert-equal \"val S\" (hash-get tst-hash #\\S))
(hash-remove! tst-hash 'key2)
(test::assert-equal 3 (length (hash-keys tst-hash)))
(test::assert-equal \"val one\" (hash-get tst-hash :key1))
(test::assert-equal \"val three\" (hash-get tst-hash \"key3\"))
(test::assert-equal \"val S\" (hash-get tst-hash #\\S))
(hash-remove! tst-hash :key1)
(test::assert-equal 2 (length (hash-keys tst-hash)))
(test::assert-equal \"val three\" (hash-get tst-hash \"key3\"))
(test::assert-equal \"val S\" (hash-get tst-hash #\\S))
(hash-remove! tst-hash \"key3\")
(test::assert-equal 1 (length (hash-keys tst-hash)))
(test::assert-equal \"val S\" (hash-get tst-hash #\\S))
(hash-remove! tst-hash #\\S)
(test::assert-equal 0 (length (hash-keys tst-hash)))


hash-set! Type: Function
root::hash-set! Usage: (hash-set! hashmap key value)

Add or update a hashmap key’s value. This is a destructive form!

Example:
(def tst-hash (make-hash))
(test::assert-equal 0 (length (hash-keys tst-hash)))
(hash-set! tst-hash :new-key '(1 2 3))
(test::assert-equal 1 (length (hash-keys tst-hash)))
(test::assert-equal '(1 2 3) (hash-get tst-hash :new-key))
(def tst-hash (make-hash '((:key1 . \"val one\")(key2 . \"val two\")(\"key3\" . \"val three\"))))
(test::assert-equal 3 (length (hash-keys tst-hash)))
(test::assert-equal \"val one\" (hash-get tst-hash :key1))
(test::assert-equal \"val two\" (hash-get tst-hash 'key2))
(test::assert-equal \"val three\" (hash-get tst-hash \"key3\"))
(hash-set! tst-hash :new-key '(1 2 3))
(test::assert-equal 4 (length (hash-keys tst-hash)))
(test::assert-equal \"val one\" (hash-get tst-hash :key1))
(test::assert-equal \"val two\" (hash-get tst-hash 'key2))
(test::assert-equal \"val three\" (hash-get tst-hash \"key3\"))
(test::assert-equal '(1 2 3) (hash-get tst-hash :new-key))
(hash-set! tst-hash 'key2 \"val two b\")
(hash-set! tst-hash :key1 \"val one b\")
(hash-set! tst-hash \"key3\" \"val three b\")
(test::assert-equal 4 (length (hash-keys tst-hash)))
(test::assert-equal \"val one b\" (hash-get tst-hash :key1))
(test::assert-equal \"val two b\" (hash-get tst-hash 'key2))
(test::assert-equal \"val three b\" (hash-get tst-hash \"key3\"))
(test::assert-equal '(1 2 3) (hash-get tst-hash :new-key))


make-hash Type: Function
root::make-hash Usage: (make-hash associations?)

Make a new hash map. If associations is provided (makes an empty map if not) then it is a list of pairs (key . value) that populate the intial map. Neither key nor value in the associations will be evaluated.

Example:
(def tst-hash (make-hash))
(test::assert-equal 0 (length (hash-keys tst-hash)))
(def tst-hash (make-hash ()))
(test::assert-equal 0 (length (hash-keys tst-hash)))
(def tst-hash (make-hash nil))
(test::assert-equal 0 (length (hash-keys tst-hash)))
(def tst-hash (make-hash '((:key1 . \"val one\")(key2 . \"val two\")(\"key3\" . \"val three\"))))
(test::assert-equal 3 (length (hash-keys tst-hash)))
(test::assert-equal \"val one\" (hash-get tst-hash :key1))
(test::assert-equal \"val two\" (hash-get tst-hash 'key2))
(test::assert-equal \"val three\" (hash-get tst-hash \"key3\"))
(def tst-hash (make-hash '#((:keyv1 . \"val one\")(keyv2 . \"val two\")(\"keyv3\" . \"val three\"))))
(test::assert-equal 3 (length (hash-keys tst-hash)))
(test::assert-equal \"val one\" (hash-get tst-hash :keyv1))
(test::assert-equal \"val two\" (hash-get tst-hash 'keyv2))
(test::assert-equal \"val three\" (hash-get tst-hash \"keyv3\"))
; Not in test below that tst-hash-val is NOT evaluated so the symbol is the value.
(def tst-hash-val \"some val\")
(def tst-hash (make-hash '#((:keyv1 . \"val one\")(:keyv2 . \"val two\")(:keyv3 . tst-hash-val))))
(test::assert-equal 3 (length (hash-keys tst-hash)))
(test::assert-equal \"val one\" (hash-get tst-hash :keyv1))
(test::assert-equal \"val two\" (hash-get tst-hash :keyv2))
(test::assert-equal 'tst-hash-val (hash-get tst-hash :keyv3))


Iterator forms

append Type: Lambda
iterator::append Usage: (append first-iter &rest rest-iters)

Combine the provided items into a single iterator (calls iter on each parameter). If non-list items are passed they are wrapped in a singleton iterator (i.e. will work with loose object). Note that nil is an empty list not a “loose item”.

Example:
(def test-iter (append '(0 1 2) '#(3 4 5) '(6 7 8 9)))
(assert-false (test-iter :empty?))
(assert-equal 10 (test-iter :count))
(assert-true (test-iter :empty?))
(def test-iter (append '(0 1 2) 3 4 5 '(6 7 8 9)))
(assert-false (test-iter :empty?))
(assert-equal 10 (test-iter :count))
(assert-true (test-iter :empty?))
(def test-iter (append 0 1 2 '(3 4)))
(assert-false (test-iter :empty?))
(assert-equal 0 (test-iter :next!))
(assert-equal 1 (test-iter :next!))
(assert-equal 2 (test-iter :next!))
(assert-equal 3 (test-iter :next!))
(assert-equal 4 (test-iter :next!))
(assert-true (test-iter :empty?))
(def test-iter (append 0 1 2 nil))
(assert-false (test-iter :empty?))
(assert-equal 0 (test-iter :next!))
(assert-equal 1 (test-iter :next!))
(assert-equal 2 (test-iter :next!))
(assert-true (test-iter :empty?))
(def test-iter (append 0 1 2 '(nil)))
(assert-false (test-iter :empty?))
(assert-equal 0 (test-iter :next!))
(assert-equal 1 (test-iter :next!))
(assert-equal 2 (test-iter :next!))
(assert-equal nil (test-iter :next!))
(assert-true (test-iter :empty?))


append-iter Type: Lambda
iterator::append-iter Usage: (append-iter)

Iterator that appends multiple iterators. Append iter will consume the iterators it is appending. If non-list items are passed they are wrapped in a singleton iterator (i.e. will work with loose object). attribute: iters private method: :next! method: :empty? method: :init impl iterator::iterator

Example:
(def test-iter ((iterator::append-iter) :init '(0 1 2) '#(3 4 5) '(6 7 8 9)))
(def test-slice-iter (test-iter :slice 3 7))
(assert-false (test-slice-iter :empty?))
(assert-equal 3 (test-slice-iter :next!))
(assert-equal 4 (test-slice-iter :next!))
(assert-equal 5 (test-slice-iter :next!))
(assert-equal 6 (test-slice-iter :next!))
(assert-true (test-slice-iter :empty?))
(def test-iter ((iterator::append-iter) :init '(0 1 2) nil '#(3 4 5) nil '(6 7 8 9)))
(def test-slice-iter (test-iter :slice 0 4))
(assert-false (test-slice-iter :empty?))
(assert-equal 0 (test-slice-iter :next!))
(assert-equal 1 (test-slice-iter :next!))
(assert-equal 2 (test-slice-iter :next!))
(assert-equal 3 (test-slice-iter :next!))
(assert-true (test-slice-iter :empty?))
(def test-iter ((iterator::append-iter) :init '(0 1 2) '#(3 4 5) '(6 7 8 9)))
(def test-slice-iter (test-iter :slice 7))
(assert-false (test-slice-iter :empty?))
(assert-equal 7 (test-slice-iter :next!))
(assert-equal 8 (test-slice-iter :next!))
(assert-equal 9 (test-slice-iter :next!))
(assert-true (test-slice-iter :empty?))
(def test-iter ((iterator::append-iter) :init '(0 1 2) '#(3 4 5) '(6 7 8 9)))
(assert-false (test-iter :empty?))
(assert-equal 10 (test-iter :count))
(assert-true (test-iter :empty?))
(def test-iter ((iterator::append-iter) :init '(0 1 2) '() '#(3 4 5) nil '(6 7 8 9)))
(assert-false (test-iter :empty?))
(assert-equal 10 (test-iter :count))
(assert-true (test-iter :empty?))
(def test-iter ((iterator::append-iter) :init nil '(0 1 2) (vec) '#(3 4 5) '(6 7 8 9) nil))
(assert-false (test-iter :empty?))
(assert-equal 10 (test-iter :count))
(assert-true (test-iter :empty?))


append-to! Type: Lambda
iterator::append-to! Usage: (append-to! ret &rest others)

Combine the provided items after the first (first must be a vector or list) into a single iterator. These values are added the first argument destructively. If non-list items are passed they are wrapped in a singleton iterator (i.e. will work with loose object). Note that nil is an empty list not a “loose item”.

Example:
(def test-iter '(0 1 2))
(append-to! test-iter '#(3 4 5) '(6 7 8 9))
(set! test-iter (iter test-iter))
(def test-slice-iter (test-iter :slice 3 7))
(assert-false (test-slice-iter :empty?))
(assert-equal 3 (test-slice-iter :next!))
(assert-equal 4 (test-slice-iter :next!))
(assert-equal 5 (test-slice-iter :next!))
(assert-equal 6 (test-slice-iter :next!))
(assert-true (test-slice-iter :empty?))
(def test-iter '(0 1 2))
(append-to! test-iter '#(3 4 5) '(6 7 8 9))
(set! test-iter (iter test-iter))
(def test-slice-iter (test-iter :slice 0 4))
(assert-false (test-slice-iter :empty?))
(assert-equal 0 (test-slice-iter :next!))
(assert-equal 1 (test-slice-iter :next!))
(assert-equal 2 (test-slice-iter :next!))
(assert-equal 3 (test-slice-iter :next!))
(assert-true (test-slice-iter :empty?))
(def test-iter '(0 1 2))
(append-to! test-iter '#(3 4 5) '(6 7 8 9))
(set! test-iter (iter test-iter))
(def test-slice-iter (test-iter :slice 7))
(assert-false (test-slice-iter :empty?))
(assert-equal 7 (test-slice-iter :next!))
(assert-equal 8 (test-slice-iter :next!))
(assert-equal 9 (test-slice-iter :next!))
(assert-true (test-slice-iter :empty?))
(def test-iter '(0 1 2))
(append-to! test-iter '#(3 4 5) '(6 7 8 9))
(set! test-iter (iter test-iter))
(assert-false (test-iter :empty?))
(assert-equal 10 (test-iter :count))
(assert-true (test-iter :empty?))
(def test-iter nil)
(append-to! test-iter nil '(0 1 2) nil '#(3 4 5) '(6 7 8 9) nil)
(set! test-iter (iter test-iter))
(assert-false (test-iter :empty?))
(assert-equal 10 (test-iter :count))
(assert-true (test-iter :empty?))
(def test-iter (vec 0))
(append-to! test-iter nil '#(1) '(2 3) nil)
(set! test-iter (iter test-iter))
(assert-false (test-iter :empty?))
(assert-equal 0 (test-iter :next!))
(assert-equal 1 (test-iter :next!))
(assert-equal 2 (test-iter :next!))
(assert-equal 3 (test-iter :next!))
(assert-true (test-iter :empty?))


collect Type: Lambda
iterator::collect Usage: (collect s)

Collect all the values into a list. This will consume the iterator and produce a new list. Will call iter on input to turn a collection into an iterator.

Example:
(def collect-test (iterator::collect '#(1 2 3)))
(assert-true (list? collect-test))
(assert-equal '(1 2 3) collect-test)


collect-str Type: Lambda
iterator::collect-str Usage: (collect-str s)

Collect all the values into a string. This will consume the iterator and produce a new string. Will call iter on input to turn a collection into an iterator.

Example:
(def collect-str-test (iterator::collect-str (iterator::map (fn (ch) (char-upper ch)) "λabc σ")))
(assert-true (string? collect-str-test))
(assert-equal "ΛABC Σ" collect-str-test)


collect-vec Type: Lambda
iterator::collect-vec Usage: (collect-vec s)

Collect all the values into a vector. This will consume the iterator and produce a new vector. Will call iter on input to turn a collection into an iterator.

Example:
(def collect-vec-test (iterator::collect-vec '(1 2 3)))
(assert-true (vec? collect-vec-test))
(assert-equal '#(1 2 3) collect-vec-test)


double-ended-iter? Type: Lambda
iterator::double-ended-iter? Usage: (double-ended-iter? thing)

Return true if thing is an iterator and double ended, nil otherwise.

Example:
(struct::defstruct test-iter
; fields
(current 0)
; methods
(:fn next! (self) (do (def val current)(set! current (+ 1 current)) val))
(:fn empty? (self) (>= current 3))
(:impl iterator::iterator))
(assert-true (iterator::double-ended-iter? (iterator::iter '(1 2 3))))
(assert-false (iterator::double-ended-iter? '(1 2 3)))
(assert-false (iterator::double-ended-iter? (test-iter)))


double-ended-iterator Type: Lambda
iterator::double-ended-iterator Usage: (defstruct iter (:fn next! (self)...)(:fn next-back! (self)...)(:fn empty? (self)...)(:impl iterator::iterator iterator::double-ended-iterator))

Trait that makes an iterator double ended (can get items from front and back. Requires a struct to define methods next-back! and implement iterator. Note that next! and next-back! can not cross, the iterator is empty when they meet. method: :nth-back! Consume the iterator until the nth element from the end and return it (0 based). Note that repeated called to nth-back! will return new data since it consumes the iterator. method: :reverse Produce an iterator that is the reverse of self.

Example:
(ns-import 'struct)
(ns-import 'iterator)
(defstruct test-double-iter
; fields
(current 0)
(current-end 2)
; methods
(:fn next! (self) (do (var val current)(set! current (+ 1 current)) val))
(:fn next-back! (self) (do (var val current-end)(set! current-end (- current-end 1)) val))
(:fn empty? (self) (> current current-end))
(:impl iterator::iterator iterator::double-ended-iterator))
(def tmap (test-double-iter))
(assert-false (tmap :empty?))
(assert-equal 0 (tmap :next!))
(assert-equal 1 (tmap :next!))
(assert-equal 2 (tmap :next!))
(assert-true (tmap :empty?))
(def tmap (test-double-iter))
(assert-false (tmap :empty?))
(assert-equal 2 (tmap :next-back!))
(assert-equal 1 (tmap :next-back!))
(assert-equal 0 (tmap :next-back!))
(assert-true (tmap :empty?))
(def tmap (test-double-iter))
(assert-false (tmap :empty?))
(assert-equal 0 (tmap :next!))
(assert-equal 2 (tmap :next-back!))
(assert-equal 1 (tmap :next-back!))
(assert-true (tmap :empty?))
; :nth-back! Example
(def tmap ((vec-iter) :init '#(0 1 2 3 4) 0))
(assert-false (tmap :empty?))
(assert-equal 4 (tmap :nth-back! 0))
(assert-equal 3 (tmap :nth-back! 0))
(assert-equal 0 (tmap :nth-back! 2))
(assert-true (tmap :empty?))
; :reverse Example
(def tmap ((test-double-iter) :reverse))
(assert-false (tmap :empty?))
(assert-equal 2 (tmap :next!))
(assert-equal 1 (tmap :next!))
(assert-equal 0 (tmap :next!))
(assert-true (tmap :empty?))


empty? Type: Lambda
iterator::empty? Usage: (empty? s)

Is an iterator empty (no more items)? Will call iter on input first.

Example:
(assert-true (iterator::empty? nil))
(assert-true (iterator::empty? '#()))
(assert-false (iterator::empty? '#(1)))


file-iter Type: Lambda
iterator::file-iter Usage: (file-iter)

Iterator that wraps a file. Each call to next! returns the next line (with trailing newline. attribute: file private attribute: next-line private method: :next! method: :empty? method: :init impl iterator::iterator

Example:
(def tst-file (open "/tmp/file-iter-test.txt" :create :truncate))
(write-line tst-file "line 1")
(write-line tst-file "line 2")
(write-line tst-file "line 3")
(write-string tst-file "line 4")
(close tst-file)
(def test-iter ((iterator::file-iter) :init (open "/tmp/file-iter-test.txt")))
(assert-false (test-iter :empty?))
(assert-equal "line 1\n" (test-iter :next!))
(assert-equal "line 2\n" (test-iter :next!))
(assert-equal "line 3\n" (test-iter :next!))
(assert-equal "line 4" (test-iter :next!))
(assert-true (test-iter :empty?))


filter Type: Lambda
iterator::filter Usage: (filter predicate items)

Returns a filter-iter around items (will call iter on items). Iterator that applies a lambda to each element to determine if is returned- is lazy.

Example:
(def test-iter (iterator::filter (fn (x) (not (= x 2))) '(1 2 3)))
(assert-false (test-iter :empty?))
(assert-equal 1 (test-iter :next!))
(assert-equal 3 (test-iter :next!))
(assert-true (test-iter :empty?))


filter-iter Type: Lambda
iterator::filter-iter Usage: (filter-iter)

Iterator that applies a lambda to each element to determine if is returned- is lazy. attribute: data private attribute: predicate private attribute: next private attribute: is-empty private method: :next! method: :empty? method: :advance-data! method: :init impl iterator::iterator

Example:
(def test-iter (((iterator::list-iter) :init '(1 2 3)) :filter (fn (x) (not (= x 2)))))
(assert-false (test-iter :empty?))
(assert-equal 1 (test-iter :next!))
(assert-equal 3 (test-iter :next!))
(assert-true (test-iter :empty?))


for Type: Macro
iterator::for Usage: (for bind in items body)

Loops over each element in an iterator. Will call iter on the input object. bind is bound to the current element of items and is accesible in body. body is evaluated a number of times equal to the the number of items in in_list.

Example:
(def i 0)
(iterator::for x in (iterator::range 11) (set! i (+ 1 i)))
(assert-equal 11 i)


for-i Type: Macro
iterator::for-i Usage: (for-i idx-bind bind in items body)

Loops over each element in an iterator. Will call iter on the input object. idx-bind is bound to an incrementing number starting with 0. bind is bound to the current element of items and is accesible in body. body is evaluated a number of times equal to the the number of items in in_list.

Example:
(def i 0)
(def i-tot 0)
(for-i idx x in '(1 2 3 4 5 6 7 8 9 10 11) (do (set! i-tot (+ idx i-tot))(set! i (+ 1 i))))
(assert-equal 11 i)
(assert-equal 55 i-tot)


interleave Type: Lambda
iterator::interleave Usage: (interleave fst scnd)

interleaves two iterators together. Resultant iter is double length of fst unless scnd has less items. Then iter is double length of scnd.

Example:
(ns-import 'iterator)
(test::assert-equal (list 1 2 3 4) (collect (interleave (iter (list 1 3)) (iter (list 2 4)))))
(test::assert-equal (list 1 2 3 4) (collect (interleave (iter (list 1 3)) (iter (list 2 4 5)))))


interleave-iter Type: Lambda
iterator::interleave-iter Usage: (interleave-iter)

create iterator that interleaves two iterators together. Resultant iter is double length of fst if fst has less items, or double length of scnd if scnd has less items. attribute: fst private attribute: scnd private attribute: flip-flop private method: :next! method: :empty? method: :init impl iterator::iterator impl iterator::double-ended-iterator

Example:


iter Type: Lambda
iterator::iter Usage: (iter thing)

Return thing as an iterator if possible (if it is an iterator just return thing).

Example:
(assert-true (iterator::iter? (iterator::iter '(1 2 3))))
(assert-true (iterator::iter? (iterator::iter '#(1 2 3))))
(assert-true (iterator::iter? (iterator::iter "abc")))
(assert-true (iterator::iter? (iterator::iter (iterator::iter '(1 2 3)))))


iter? Type: Lambda
iterator::iter? Usage: (iter? thing)

Return true if thing is an iterator, nil otherwise.

Example:
(assert-true (iterator::iter? (iterator::iter '(1 2 3))))
(assert-false (iterator::iter? '(1 2 3)))


iterator Type: Lambda
iterator::iterator Usage: (defstruct iter (:fn next! (self)...)(:fn empty? (self)...)(:impl iterator::iterator))

Trait that provides iterator methods. Requires a struct to define methods next! and empty? method: :collect Collect all the values into a list. This will consume the iterator and produce a new list. method: :collect-vec Collect all the values into a vector. This will consume the iterator and produce a new list. method: :collect-str Collect all the values into a string. This will consume the iterator and produce a new string. method: :map Apply the provided function to each element of the iterator. Map is lazy. method: :filter Apply the provided predicate to the iterator producing only elements that are true. Filter is lazy. method: :slice method: :count Consume the iterator and return the number of items. method: :nth! Consume the iterator until the nth! element and return it (0 based). Note that repeated called to nth! will return new data since it consumes the iterator. method: :double-ended? Return t if this iterator is double ended, nil otherwise.

Example:
(ns-import 'struct)
(ns-import 'iterator)
(defstruct test-iter
; fields
(current 0)
; methods
(:fn next! (self) (do (def val current)(set! current (+ 1 current)) val))
(:fn empty? (self) (>= current 3))
(:impl iterator::iterator))
(def tmap (test-iter))
(assert-false (tmap :empty?))
(assert-equal 0 (tmap :next!))
(assert-equal 1 (tmap :next!))
(assert-equal 2 (tmap :next!))
(assert-true (tmap :empty?))
; :collect Example
(def collect-test ((iter '#(1 2 3)) :collect))
(assert-true (list? collect-test))
(assert-equal '(1 2 3) collect-test)
; :collect-vec Example
(def collect-vec-test ((iter '(1 2 3)) :collect-vec))
(assert-true (vec? collect-vec-test))
(assert-equal '#(1 2 3) collect-vec-test)
; :collect-str Example
(def collect-str-test (((iter "λabc σ") :map (fn (ch) (char-upper ch))) :collect-str))
(assert-true (string? collect-str-test))
(assert-equal "ΛABC Σ" collect-str-test)
; :map Example
(def tmap ((test-iter) :map (fn (x) (+ 1 x))))
(assert-false (tmap :empty?))
(assert-equal 1 (tmap :next!))
(assert-equal 2 (tmap :next!))
(assert-equal 3 (tmap :next!))
(assert-true (tmap :empty?))
; :filter Example
(def tmap ((test-iter) :filter (fn (x) (not (= x 1)))))
(assert-false (tmap :empty?))
(assert-equal 0 (tmap :next!))
(assert-equal 2 (tmap :next!))
(assert-true (tmap :empty?))
; :count Example
(def tmap (test-iter))
(assert-false (tmap :empty?))
(assert-equal 3 (tmap :count))
(assert-true (tmap :empty?))
; :nth! Example
(def tmap ((list-iter) :init '(0 1 2 3 4)))
(assert-false (tmap :empty?))
(assert-equal 0 (tmap :nth! 0))
(assert-equal 1 (tmap :nth! 0))
(assert-equal 4 (tmap :nth! 2))
(assert-true (tmap :empty?))
; :double-ended? Example
(ns-import 'struct)
(ns-import 'iterator)
(defstruct test-double-iter
; fields
(current 0)
(current-end 2)
; methods
(:fn next! (self) (do (def val current)(set! current (+ 1 current)) val))
(:fn next-back! (self) (do (def val current-end)(set! current-end (- current-end 1)) val))
(:fn empty? (self) (> current current-end))
(:impl iterator::iterator iterator::double-ended-iterator))
(assert-false ((test-iter) :double-ended?))
(assert-true ((test-double-iter) :double-ended?))


list-iter Type: Lambda
iterator::list-iter Usage: (list-iter)

Iterator that wraps a list. attribute: data private attribute: rev-data private attribute: elements private method: :next! method: :next-back! method: :empty? method: :init method: :make-rev impl iterator::iterator impl iterator::double-ended-iterator

Example:
(def test-list-iter ((list-iter) :init '(1 2 3)))
(assert-false (test-list-iter :empty?))
(assert-equal 1 (test-list-iter :next!))
(assert-equal 2 (test-list-iter :next!))
(assert-equal 3 (test-list-iter :next!))
(assert-true (test-list-iter :empty?))
(def test-list-iter ((list-iter) :init '(1 2 3)))
(assert-false (test-list-iter :empty?))
(assert-equal 1 (test-list-iter :next!))
(assert-equal 3 (test-list-iter :next-back!))
(assert-equal 2 (test-list-iter :next!))
(assert-true (test-list-iter :empty?))
(def test-list-iter ((list-iter) :init '(1 2 3)))
(assert-false (test-list-iter :empty?))
(assert-equal 3 (test-list-iter :next-back!))
(assert-equal 2 (test-list-iter :next-back!))
(assert-equal 1 (test-list-iter :next-back!))
(assert-true (test-list-iter :empty?))


map Type: Lambda
iterator::map Usage: (map map-fn items)

Returns a map-iter around items (will call iter on items). Apply the provided function to each element of the iterator. Map is lazy.

Example:
(def tmap (iterator::map (fn (x) (+ 1 x)) '(0 1 2)))
(assert-false (tmap :empty?))
(assert-equal 1 (tmap :next!))
(assert-equal 2 (tmap :next!))
(assert-equal 3 (tmap :next!))
(assert-true (tmap :empty?))
(def tmap (iterator::reverse (iterator::map (fn (x) (+ 1 x)) '(0 1 2))))
(assert-false (tmap :empty?))
(assert-equal 3 (tmap :next!))
(assert-equal 2 (tmap :next!))
(assert-equal 1 (tmap :next!))
(assert-true (tmap :empty?))


map-iter Type: Lambda
iterator::map-iter Usage: (map-iter)

Iterator that applies a lambda to each element of another iterator- is lazy. attribute: data private attribute: map-fn private method: :next! method: :next-back! method: :empty? method: :init method: :double-ended? impl iterator::iterator impl iterator::double-ended-iterator

Example:
(def test-map-iter (((iterator::list-iter) :init '(1 2 3)) :map (fn (x) (* x 2))))
(assert-false (test-map-iter :empty?))
(assert-equal 2 (test-map-iter :next!))
(assert-equal 4 (test-map-iter :next!))
(assert-equal 6 (test-map-iter :next!))
(assert-true (test-map-iter :empty?))


meld Type: Lambda
iterator::meld Usage: (meld fst scnd)

melds two iterators together. Resultant iter is composed of pairs (fst, scnd) for each value of next! in each provided iterator. Length of returned iter is equal to length of the shortest provided iterator.

Example:
(ns-import 'iterator)
(test::assert-equal (list (join 'string 'bean) (join 'monte 'carlo)) (collect (meld (iter (list 'string 'monte)) (iter (list 'bean 'carlo)))))
(test::assert-equal (list (join 1 2) (join 3 4)) (collect (meld (iter (list 1 3)) (iter (list 2 4 5)))))


meld-iter Type: Lambda
iterator::meld-iter Usage: (meld-iter)

create iterator that melds two iterators together. Resultant iter is composed of pairs (fst, scnd) for each value of next! in each provided iterator. Length of meld-iter is equal to length of shorter iterator. attribute: fst private attribute: scnd private attribute: flip-flop private method: :next! method: :empty? method: :init impl iterator::iterator impl iterator::double-ended-iterator

Example:


next! Type: Lambda
iterator::next! Usage: (next! s)

Calls iter on s and returns the next item.

Example:
(assert-equal 1 (iterator::next! '(1 2 3)))
(assert-equal 1 (iterator::next! '#(1 2 3)))
(def next-test (iterator::iter '(4 5 6)))
(assert-equal 4 (iterator::next! next-test))
(assert-equal 5 (iterator::next! next-test))
(assert-equal 6 (iterator::next! next-test))
(assert-true (next-test :empty?))


nth Type: Lambda
iterator::nth Usage: (nth idx coll)

Consume the iterator until the idx (nth) element and return it (0 based). Note that repeated called to nth will return new data since it consumes the iterator.

Example:
(def tmap ((list-iter) :init '(0 1 2 3 4)))
(assert-false (tmap :empty?))
(assert-equal 0 (nth 0 tmap))
(assert-equal 1 (nth 0 tmap))
(assert-equal 4 (nth 2 tmap))
(assert-true (tmap :empty?))


range Type: Lambda
iterator::range Usage: (range &rest i)

Create an iterator that generates numbers within a range. Can be called with one int (n) to produce 0..(n-1) or with two ints (m, n) to produce m..n.

Example:
(def test-iter (iterator::range 3 6))
(assert-false (test-iter :empty?))
(assert-equal 3 (test-iter :next!))
(assert-equal 4 (test-iter :next!))
(assert-equal 5 (test-iter :next!))
(assert-equal 6 (test-iter :next!))
(assert-true (test-iter :empty?))
(def test-iter (iterator::range 3))
(assert-false (test-iter :empty?))
(assert-equal 0 (test-iter :next!))
(assert-equal 1 (test-iter :next!))
(assert-equal 2 (test-iter :next!))
(assert-true (test-iter :empty?))


range-iter Type: Lambda
iterator::range-iter Usage: (range-iter)

Iterator that generates numbers within a range. attribute: start private attribute: end private method: :next! method: :next-back! method: :empty? method: :init method: :count impl iterator::iterator impl iterator::double-ended-iterator

Example:
(def test-iter ((range-iter) :init 3 6))
(assert-false (test-iter :empty?))
(assert-equal 3 (test-iter :next!))
(assert-equal 4 (test-iter :next!))
(assert-equal 5 (test-iter :next!))
(assert-equal 6 (test-iter :next!))
(assert-true (test-iter :empty?))
(def test-iter ((range-iter) :init 3 6))
(assert-false (test-iter :empty?))
(assert-equal 6 (test-iter :next-back!))
(assert-equal 5 (test-iter :next-back!))
(assert-equal 4 (test-iter :next-back!))
(assert-equal 3 (test-iter :next-back!))
(assert-true (test-iter :empty?))


reduce Type: Lambda
iterator::reduce Usage: (reduce reducing-fcn init-val coll)

reduce is used to amalgamate a provided iterator, coll, and an intitial value, according to the reducing function provided. The iter function will be called on coll to make sure it is an iterator. The reducing-fcn should be a function of two arguments. In the first iteration of reduce, the init-val will be used as the first argument to the reducing-fcn and (next! coll) will be used as the second argument. For all subsequent iterations, The result from the previous application of the reducing-fcn will be used as the first argument to the reducing-fcn and the second argument will be the next item in the collection when the collection is empty reduce will return the amalgamated result.

Example:
(assert-true (= 15 (reduce + 0 (list 1 2 3 4 5))))
(assert-false (= 15 (reduce + 1 (list 1 2 3 4 5))))
(assert-true (= "one hoopy frood" (reduce str "" (list "one " "hoopy " "frood"))))


reduce-times Type: Lambda
iterator::reduce-times Usage: (reduce-times value wrapping-fcn times)

Apply wrapping-fcn to value number of times. Function is recursive. Recursive binding for value is previous application of wrapping function to value.

Example:
(assert-equal (list (list 3)) (reduce-times 3 list 2))
(assert-equal 5 (reduce-times (reduce-times 5 list 5) first 5))


repeat Type: Lambda
iterator::repeat Usage: (repeat target &rest n)

repeat target n times. if n is not provided returns infinite iterator.

Example:
(test::assert-equal (list #\m #\m #\m #\m) (collect (repeat #\m 4)))
(test::assert-equal (list #\m #\m #\m #\m) (collect (take (repeat #\m) 4)))


repeat-iter Type: Lambda
iterator::repeat-iter Usage: (repeat-iter)

iterator that returns provided repeat with specified length. if length is negative returns infinite iterator. attribute: to-repeat private attribute: len private attribute: current private method: :empty? method: :next! method: :init impl iterator::iterator

Example:


reverse Type: Lambda
iterator::reverse Usage: (reverse items)

Produce an iterator the is the reverse of items. Will call iter on items and requires a double ended iterator.

Example:
(def tmap (reverse ((vec-iter) :init '#(0 1 2) 0)))
(assert-false (tmap :empty?))
(assert-equal 2 (tmap :next!))
(assert-equal 1 (tmap :next!))
(assert-equal 0 (tmap :next!))
(assert-true (tmap :empty?))
(assert-error (reverse "string"))


reverse-iter Type: Lambda
iterator::reverse-iter Usage: (reverse-iter)

Iterator that reverses another iterators direction. Requires a double ended iterator. attribute: wrapped private method: :next! method: :next-back! method: :empty? method: :init impl iterator::iterator impl iterator::double-ended-iterator

Example:
(def test-iter (((vec-iter) :init '#(1 2 3) 0) :reverse))
(assert-false (test-iter :empty?))
(assert-equal 3 (test-iter :next!))
(assert-equal 2 (test-iter :next!))
(assert-equal 1 (test-iter :next!))
(assert-true (test-iter :empty?))


slice Type: Lambda
iterator::slice Usage: (slice items start &rest end)

Provides a slice of iterator. Will call iter on items. Slice iter will consume the iterator it is slicing.

Example:
(def test-slice-iter (slice '(0 1 2 3 4 5 6 7 8 9) 3 6))
(assert-false (test-slice-iter :empty?))
(assert-equal 3 (test-slice-iter :next!))
(assert-equal 4 (test-slice-iter :next!))
(assert-equal 5 (test-slice-iter :next!))
(assert-true (test-slice-iter :empty?))
(def test-slice-iter (slice '(0 1 2 3 4 5 6 7 8 9) 0 3))
(assert-false (test-slice-iter :empty?))
(assert-equal 0 (test-slice-iter :next!))
(assert-equal 1 (test-slice-iter :next!))
(assert-equal 2 (test-slice-iter :next!))
(assert-true (test-slice-iter :empty?))
(def test-slice-iter (slice '(0 1 2 3 4 5 6 7 8 9) 7))
(assert-false (test-slice-iter :empty?))
(assert-equal 7 (test-slice-iter :next!))
(assert-equal 8 (test-slice-iter :next!))
(assert-equal 9 (test-slice-iter :next!))
(assert-true (test-slice-iter :empty?))


slice-iter Type: Lambda
iterator::slice-iter Usage: (slice-iter)

Iterator that provides a slice of the underlying iter. Slice iter will consume the iterator it is slicing. attribute: data private attribute: start private attribute: total private attribute: count private method: :next! method: :empty? method: :init impl iterator::iterator

Example:
(def test-slice-iter (((iterator::list-iter) :init '(0 1 2 3 4 5 6 7 8 9)) :slice 3 6))
(assert-false (test-slice-iter :empty?))
(assert-equal 3 (test-slice-iter :next!))
(assert-equal 4 (test-slice-iter :next!))
(assert-equal 5 (test-slice-iter :next!))
(assert-true (test-slice-iter :empty?))
(def test-slice-iter (((iterator::list-iter) :init '(0 1 2 3 4 5 6 7 8 9)) :slice 0 3))
(assert-false (test-slice-iter :empty?))
(assert-equal 0 (test-slice-iter :next!))
(assert-equal 1 (test-slice-iter :next!))
(assert-equal 2 (test-slice-iter :next!))
(assert-true (test-slice-iter :empty?))
(def test-slice-iter (((iterator::list-iter) :init '(0 1 2 3 4 5 6 7 8 9)) :slice 7))
(assert-false (test-slice-iter :empty?))
(assert-equal 7 (test-slice-iter :next!))
(assert-equal 8 (test-slice-iter :next!))
(assert-equal 9 (test-slice-iter :next!))
(assert-true (test-slice-iter :empty?))


string-iter Type: Lambda
iterator::string-iter Usage: (string-iter)

Iterator that wraps a string. attribute: data private method: :next! method: :empty? method: :init impl iterator::iterator

Example:
(def test-string-iter ((string-iter) :init "123"))
(assert-false (test-string-iter :empty?))
(assert-equal #\1 (test-string-iter :next!))
(assert-equal #\2 (test-string-iter :next!))
(assert-equal #\3 (test-string-iter :next!))
(assert-true (test-string-iter :empty?))


take Type: Lambda
iterator::take Usage: (take provided-iter n)

return iterator with first n items of provided-iter. Returned iterator is the same as provided-iter if n is greater than the length of provided-iter.

Example:
(test::assert-equal (list #\m #\m) (collect (take (repeat #\m 4) 2)))


take-iter Type: Lambda
iterator::take-iter Usage: (take-iter)

take itertor attribute: provided-iter private attribute: len private attribute: current private method: :empty? method: :next! method: :init impl iterator::iterator

Example:


vec-iter Type: Lambda
iterator::vec-iter Usage: (vec-iter)

Iterator that wraps a vector. attribute: data private attribute: start private attribute: end private method: :next! method: :next-back! method: :empty? method: :nth! method: :nth-back! method: :init impl iterator::iterator impl iterator::double-ended-iterator

Example:
(def test-vec-iter ((vec-iter) :init '#(1 2 3) 0))
(assert-false (test-vec-iter :empty?))
(assert-equal 1 (test-vec-iter :next!))
(assert-equal 2 (test-vec-iter :next!))
(assert-equal 3 (test-vec-iter :next!))
(assert-true (test-vec-iter :empty?))
(def test-vec-iter ((vec-iter) :init (vec) 0))
(assert-true (test-vec-iter :empty?))


Logger forms

logger Type: Lambda
root::logger Usage: (logger)

logger struct Initialize a logger object with a name and a log level that can be called repeatedly to log to stdout. Supported log levels in order are :trace, :debug, :info, :warn, :error, or :off. Calls to functions provided by struct are noops unless that particular log level is enabled. To override the log level specified in code set the environment variable SLSH_LOG_LEVEL to the desired log level before initializing the struct. Format is: {unix time} {pid} {log level}: [{logger-name}] {log-string} attribute: log-level private attribute: log-level-int private attribute: logger-name private attribute: convert-log-level private method: :get-log method: :log-it method: :trace method: :debug method: :info method: :warn method: :error method: :init

Example:
(defn test-logger (log-name log-level)
(let ((a-logger ((logger) :init log-name log-level))
(str-list (list)))
(append-to! str-list (list (a-logger :get-log :trace (str "test log " log-level))))
(append-to! str-list (list (a-logger :get-log :debug (str "test log " log-level))))
(append-to! str-list (list (a-logger :get-log :info (str "test log " log-level))))
(append-to! str-list (list (a-logger :get-log :warn (str "test log " log-level))))
(append-to! str-list (list (a-logger :get-log :error (str "test log " log-level))))
(collect (filter (fn (x) (not (falsey? x))) str-list))))
(test::assert-equal 5 (length (test-logger "test-logger" :trace)))
(test::assert-equal 4 (length (test-logger "test-logger" :debug)))
(test::assert-equal 3 (length (test-logger "test-logger" :info)))
(test::assert-equal 2 (length (test-logger "test-logger" :warn)))
(test::assert-equal 1 (length (test-logger "test-logger" :error)))
(test::assert-equal 0 (length (test-logger "test-logger" :off)))
(test::assert-error-msg ((logger) :init "test-logger" :bad-log-level) "log level must be a symbol one of: :trace, :debug, :info, :warn, :error, or :off")
(test::assert-error-msg ((logger) :init 'bad-log-name :error) "in-logger-name must be a string.")


Math forms

% Type: Function
root::% Usage: (% int int)

Remainder from dividing first int by the second.

Example:
(ns-import 'math)
(test::assert-equal 0 (% 50 10))
(test::assert-equal 5 (% 55 10))
(test::assert-equal 1 (% 1 2))
(test::assert-error (%))
(test::assert-error (% 1))
(test::assert-error (% 1 2 3))
(test::assert-error (% 1 2.0))


* Type: Function
root::* Usage: (* number*)

Multiply a sequence of numbers. (*) will return 1.

Example:
(ns-import 'math)
(test::assert-equal 1 (*))
(test::assert-equal 5 (* 5))
(test::assert-equal 5 (* 1 5))
(test::assert-equal 5.0 (* 1.0 5))
(test::assert-equal 7.5 (* 1.5 5))
(test::assert-equal 7.5 (* 1.5 5.0))
(test::assert-equal 15 (* 3 5))
(test::assert-equal 8 (* 1 2 4))
(test::assert-equal 16 (* 2 2 4))
(test::assert-equal 16.0 (* 2 2.0 4))
(test::assert-equal 16.0 (* 2.0 2.0 4.0))
(test::assert-equal 55.0000000001 (* 100 0.55))
(test::assert-error (* 1 2 4 "5"))


*euler* Type: Float
math::*euler* Usage: (print *e*)

Float representing euler’s number.

Example:
(ns-import 'math)
(test::assert-equal 2.718281828459045 *e*)


*pi* Type: Float
math::*pi* Usage: (print *pi*)

Float representing pi.

Example:
(ns-import 'math)
(test::assert-equal 3.141592653589793 *pi*)


+ Type: Function
root::+ Usage: (+ number*)

Add a sequence of numbers. (+) will return 0.

Example:
(ns-import 'math)
(test::assert-equal 0 (+))
(test::assert-equal 5 (+ 5))
(test::assert-equal 5 (+ (values 5)))
(test::assert-equal 5 (+ (values 5 6)))
(test::assert-equal 10 (+ 5 (values 5 6)))
(test::assert-equal 5 (+ 5.0))
(test::assert-equal 6 (+ 1 5))
(test::assert-equal 6.5 (+ 1 5.5))
(test::assert-equal 7 (+ 1 2 4))
(test::assert-error (+ 1 2 4 "5"))


- Type: Function
root::- Usage: (- number+)

Subtract a sequence of numbers. Requires at least one number (negate if only one number).

Example:
(ns-import 'math)
(test::assert-error (-))
(test::assert-error (- 5 "2"))
(test::assert-equal -5 (- 5))
(test::assert-equal -5.0 (- 5.0))
(test::assert-equal -4 (- 1 5))
(test::assert-equal -4.5 (- 1 5.5))
(test::assert-equal 4 (- 10 2 4))
(test::assert-equal 4.9 (- 10.9 2 4))


/ Type: Function
root::/ Usage: (/ number+)

Divide a sequence of numbers. Requires at least two numbers.

Example:
(ns-import 'math)
(test::assert-equal 5 (/ 50 10))
(test::assert-equal 5 (/ 50.0 10.0))
(test::assert-equal 0 (/ 1 5))
(test::assert-equal .2 (/ 1.0 5))
(test::assert-equal .2 (/ 1.0 5.0))
(test::assert-equal 5.5 (/ 5.5 1))
(test::assert-equal 2 (/ 16 2 4))
(test::assert-equal 5 (/ 100 2 5 2))
(test::assert-error (/))
(test::assert-error (/ 1))
(test::assert-error (/ 1 0))
(test::assert-error (/ 10 5 0))
(test::assert-error (/ 10 "5" 2))


2pow Type: Function
math::2pow Usage: (2pow base)

Raise 2 to power of argument.

Example:
(ns-import 'math)
(test::assert-equal 1024 (2pow 10))
(test::assert-equal (2pow (* 10 2)) (pow (2pow 10) 2))


abs Type: Function
math::abs Usage: (abs arg)

Returns absolute value of arg.

Example:
(ns-import 'math)
(test::assert-equal 2.0 (abs 2))
(test::assert-equal 144 (abs -144))
(test::assert-equal 4.53 (abs -4.53))


arccos Type: Function
math::arccos Usage: (arccos num)

Take arccos of argument

Example:
(ns-import 'math)
(test::assert-equal 0.01 (cos (arccos 0.01)))


arcsin Type: Function
math::arcsin Usage: (arcsin num)

Take arcsin of argument

Example:
(ns-import 'math)
(test::assert-equal 0.01 (sin (arcsin 0.01)))


arctan Type: Function
math::arctan Usage: (arctan num)

Take arctan of argument

Example:
(ns-import 'math)
(test::assert-equal 0.01 (tan (arctan 0.01)))


ceil Type: Function
math::ceil Usage: (ceil value)

Returns smallest integer greater than or equal to value.

Example:
(ns-import 'math)
(test::assert-equal 2.0 (ceil 2))
(test::assert-equal 145 (ceil 144.444444))
(test::assert-equal 5 (ceil 4.53))


cos Type: Function
math::cos Usage: (cos num)

Take cos of argument

Example:
(ns-import 'math)
(test::assert-equal -0.14550003380861354 (cos 8))
(test::assert-equal (cos 6) (/ (sin 6) (tan 6)))


exp Type: Function
math::exp Usage: (exp num)

Returns e ^ num, the exponential function.

Example:
(ns-import 'math)
(test::assert-equal *euler* (exp 1))
(test::assert-equal 1 (exp 0))
(test::assert-equal 42 (exp (lne 42)))


floor Type: Function
math::floor Usage: (floor value)

Returns largest integer less than or equal to value.

Example:
(ns-import 'math)
(test::assert-equal 2.0 (floor 2))
(test::assert-equal 144 (floor 144.444444))
(test::assert-equal 4 (floor 4.53))


fract Type: Function
math::fract Usage: (fract num)

Returns fractional part of a number

Example:
(ns-import 'math)
(test::assert-equal 0.9893582466233818 (fract 1911.9893582466233818))
(test::assert-equal 0.0 (fract 1911))


lne Type: Function
math::lne Usage: (lne num)

Returns natural logarithm of number

Example:
(ns-import 'math)
(def x 7.0)
(def y 11.0)
(test::assert-equal 1 (lne *euler*))
(test::assert-equal 0 (lne 1))
(test::assert-equal (lne (* x y)) (+ (lne x) (lne y)))
(test::assert-equal (lne (/ x y)) (- (lne x) (lne y)))
(test::assert-equal (lne (pow x y)) (* y (lne x)))


log Type: Function
math::log Usage: (log num base)

Returns log of number given base.

Example:
(ns-import 'math)
(test::assert-equal 8 (log 256 2))
(test::assert-equal 3 (log 27 3))
(test::assert-equal (log (pow 8 2) 10) (* 2 (log 8 10)))
(test::assert-equal 1 (log 11 11))
(test::assert-equal '-inf (log 0 11))
(test::assert-equal (log 11 5) (/ (log 11 3) (log 5 3)))


log2 Type: Function
math::log2 Usage: (log2 num)

Returns log base 2 of input.

Example:
(ns-import 'math)
(test::assert-equal 7 (log2 128))
(test::assert-equal (log 7 2) (/ 1.0 (log 2 7)))


pow Type: Function
math::pow Usage: (pow base power)

Raise first argument to power of second argument.

Example:
(ns-import 'math)
(test::assert-equal 16 (pow 4 2))
(test::assert-equal 10 (log (pow 2 10) 2))
(test::assert-equal (pow 8 15) (* (pow 8 10) (pow 8 5)))
(test::assert-equal (pow 100 3) (/ (pow 100 5) (pow 100 2)))
(test::assert-equal 1 (pow 85 0))


round Type: Function
math::round Usage: (round arg)

Round arg to nearest int value.

Example:
(ns-import 'math)
(test::assert-equal 2.0 (round 2))
(test::assert-equal 144 (round 144.444444))
(test::assert-equal 5 (round 4.53))


sin Type: Function
math::sin Usage: (sin num)

Take sin of argument

Example:
(ns-import 'math)
(test::assert-equal 0.9893582466233818 (sin 8))
(test::assert-equal (sin 6) (* (tan 6) (cos 6)))


sqrt Type: Function
math::sqrt Usage: (sqrt num)

Take square root of argument.

Example:
(ns-import 'math)
(test::assert-equal 2.0 (sqrt 4))
(test::assert-equal 2.04939015319192 (sqrt 4.2))
(test::assert-equal 12 (sqrt 144))


tan Type: Function
math::tan Usage: (tan num)

Take tan of argument

Example:
(ns-import 'math)
(test::assert-equal -6.799711455220379 (tan 8))
(test::assert-equal (tan 6) (/ (sin 6) (cos 6)))


to-degrees Type: Function
math::to-degrees Usage: (to-degrees num)

Convert degrees to radians.

Example:
(ns-import 'math)
(test::assert-equal 0 (- (to-degrees *pi*) 180))


to-radians Type: Function
math::to-radians Usage: (to-radians num)

Convert degrees to radians.

Example:
(ns-import 'math)
(test::assert-equal 0 (- *pi* (to-radians 180)))


Namespace forms

ns-auto-export Type: Macro
root::ns-auto-export Usage: (ns-auto-export symbol)

Macro that takes a symbol, the symbol of the current namespace, and writes an ns-export statement that includes all symbols defined in the namespaces scope that do not begin with the ‘-‘ symbol. This is a convenience method that allows user to avoid enumerating all symbols while also introducing a mechanism to exclude symbols from being excluded. Note, if using ns-auto-export, it is not possible to export a symbol that is already defined in another namespace, if said functionality is desired the symbol must be manually exported with another ns-export statement; ns-auto-export can be used in conjunction with ns-export.

ns-create Type: Function
root::ns-create Usage: (ns-create namespace)

Creates and enters a new a namespace (must evaluate to a string or symbol).

Example:
(ns-push 'test-ns-create)
(def test-ns-enter *ns*)
(ns-create 'ns-create-test-namespace)
(def test-symbol "testing")
(test::assert-equal "testing" test-symbol)
(ns-enter test-ns-create::test-ns-enter)
(test::assert-false (def? test-symbol))
(ns-pop)
#t


ns-enter Type: Function
root::ns-enter Usage: (ns-enter namespace)

Enters an existing namespace (must evaluate to a string or symbol).

Example:
(ns-push 'test-ns-enter)
(def test-ns-enter *ns*)
(ns-create 'ns-enter-test-namespace)
(def test-symbol "testing")
(test::assert-equal "testing" test-symbol)
(ns-enter test-ns-enter::test-ns-enter)
(test::assert-false (def? test-symbol))
(ns-enter 'ns-enter-test-namespace)
(test::assert-true (def? test-symbol))
(test::assert-equal "testing" test-symbol)
(ns-enter test-ns-enter::test-ns-enter)
(ns-pop)
#t


ns-exists? Type: Function
root::ns-exists? Usage: (ns-exists? namespace)

True if the supplied namespace exists (must evaluate to a string or symbol).

Example:
(test::assert-false (ns-exists? 'ns-exists-test-namespace))
(ns-push 'ns-exists-test-namespace)
(ns-pop)
(test::assert-true (ns-exists? 'ns-exists-test-namespace))


ns-export Type: Macro
root::ns-export Usage: (ns-export symbol_or_sequence)

Export a symbol or list of symbols to be imported into other namespaces.

ns-import Type: Macro
root::ns-import Usage: (ns-import namespace)

Import any symbols exported from namespace into the current namespace.

ns-list Type: Function
root::ns-list Usage: (ns-list)

Returns a vector of all namespaces.

Example:
(test::assert-not-includes "ns-list-test-namespace" (ns-list))
(ns-push 'ns-list-test-namespace)
(ns-pop)
(test::assert-includes "ns-list-test-namespace" (ns-list))


ns-pop Type: Macro
root::ns-pop Usage: (ns-pop)

Returns to the previous namespace saved in the last ns-push.

Example:
(def test-ns-pop *ns*)
(ns-push 'ns-pop-test-namespace)
(test::assert-equal "ns-pop-test-namespace" *active-ns*)
(ns-pop)
(test::assert-equal test-ns-pop *ns*)


ns-push Type: Macro
root::ns-push Usage: (ns-push 'namespace)

Pushes the current namespace on a stack for ns-pop and enters or creates namespace.

Example:
(def test-ns-push *ns*)
(ns-push 'ns-pop-test-namespace)
; *ns* will not be right...
(test::assert-equal "ns-pop-test-namespace" *active-ns*)
(ns-push 'ns-pop-test-namespace2)
(test::assert-equal "ns-pop-test-namespace2" *active-ns*)
(ns-pop)
(test::assert-equal "ns-pop-test-namespace" *active-ns*)
(ns-pop)
(test::assert-equal test-ns-push *ns*)


ns-symbols Type: Function
root::ns-symbols Usage: (ns-symbols namespace)

Returns the list of all symbols in namespace (must evaluate to a string or symbol).

Example:
(test::assert-includes 'loop (ns-symbols 'root))
(test::assert-not-includes 'dumb-symbol-xxx (ns-symbols 'root))
(test::assert-includes 'car (ns-symbols 'root))


Pair forms

Operations on the ‘Pair’ type (aka Cons Cell) that can be used to create traditional Lisp list structures. These are the default list structure and are produced with bare parentheses in code. These lists can also be created by building them up with joins or with the list form.

car Type: Function
root::car Usage: (car pair)

Return the car (first item) from a pair. If used on a proper list this will be the first element.

Example:
(def tst-pairs-two (list 'x 'y 'z))
(test::assert-equal 'x (car tst-pairs-two))
(test::assert-equal 10 (car '(10)))
(test::assert-equal 9 (car '(9 11 13)))


cdr Type: Function
root::cdr Usage: (cdr pair)

Return the cdr (second item) from a pair. If used on a proper list this will be the list minus the first element.

Example:
(def tst-pairs-three (list 'x 'y 'z))
(test::assert-equal '(y z) (cdr tst-pairs-three))
(test::assert-equal nil (cdr '(10)))
(test::assert-equal '(13) (cdr '(9 13)))
(test::assert-equal '(11 13) (cdr '(9 11 13)))


join Type: Function
root::join Usage: (join car cdr)

Create a pair with the provided car and cdr.

Example:
(def tst-pair-one (join 1 2))
(test::assert-equal 1 (car tst-pair-one))
(test::assert-equal 2 (cdr tst-pair-one))
(test::assert-equal '(1 2 3) (join 1 (join 2 (join 3 nil))))


list Type: Function
root::list Usage: (list item0 item1 .. itemN)

Create a proper list from pairs with items 0 - N.

Example:
(test::assert-equal '(1 2 3) (list 1 2 3))


xar! Type: Function
root::xar! Usage: (xar! pair expression)

Destructive form that replaces the car (first item) in a pair with a new expression. If used on a proper list will replace the first item. Can be used on nil to create a pair (expression . nil).

Example:
(def tst-pairs-three (list 'x 'y 'z))
(test::assert-equal '(x y z) tst-pairs-three)
(test::assert-equal '(s y z) (xar! tst-pairs-three 's))
(test::assert-equal '(s y z) tst-pairs-three)
(def tst-pairs-four nil)
(test::assert-equal '() tst-pairs-four)
(test::assert-equal '(t) (xar! tst-pairs-four 't))
(test::assert-equal '(t) tst-pairs-four)


xdr! Type: Function
root::xdr! Usage: (xdr! pair expression)

Destructive form that replaces the cdr (second item) in a pair with a new expression. If used on a proper list will replace everthing after the first item. Can be used on nil to create a pair (nil . expression).

Example:
(def tst-pairs-five (list 'a 'b 'c))
(test::assert-equal '(a b c) tst-pairs-five)
(test::assert-equal '(a y z) (xdr! tst-pairs-five '(y z)))
(test::assert-equal '(a y z) tst-pairs-five)
(def tst-pairs-six nil)
(test::assert-equal '() tst-pairs-six)
(test::assert-equal '(nil . v) (xdr! tst-pairs-six 'v))
(test::assert-equal '(nil . v) tst-pairs-six)


Pair-ext forms

caaar Type: Lambda
root::caaar Usage: (caaar lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal 1 (caaar '(((1 4) 5) (6 3) 2)))


caadr Type: Lambda
root::caadr Usage: (caadr lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal 6 (caadr '((1 4 5) (6 3) 2)))


caar Type: Lambda
root::caar Usage: (caar lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal 1 (caar '((1) 2 3)))


cadar Type: Lambda
root::cadar Usage: (cadar lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal 4 (cadar '((1 4 5) (6 3) 2)))


cadddr Type: Lambda
root::cadddr Usage: (cadddr lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal 6 (cadddr '((1 7 8) (4 5) 2 6 (3 9))))


caddr Type: Lambda
root::caddr Usage: (caddr lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal 6 (caddr '((1 4 5) 2 6)))


cadr Type: Lambda
root::cadr Usage: (cadr lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal 2 (cadr '(1 2 3)))


cdaar Type: Lambda
root::cdaar Usage: (cdaar lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal '(7 8) (cdaar '(((1 7 8) 4 5) 2 (6 3))))


cdadr Type: Lambda
root::cdadr Usage: (cdadr lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal '(9) (cdadr '(((1 7 8) 4 5) (2 9) (6 3))))


cdar Type: Lambda
root::cdar Usage: (cdar lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal '(4 5) (cdar '((1 4 5) 2 3)))


cddar Type: Lambda
root::cddar Usage: (cddar lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal '(5) (cddar '(((1 7 8) 4 5) 2 (6 3))))


cdddr Type: Lambda
root::cdddr Usage: (cdddr lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal '(3 9) (cdddr '(((1 7 8) 4 5) 2 6 3 9)))


cddr Type: Lambda
root::cddr Usage: (cddr lst)

Shorthand for car/cdr calls (a is car, d is cdr)

Example:
(assert-equal '(3) (cddr '((1 4 5) 2 3)))


Random forms

probool Type: Function
root::probool Usage: (probool), (probool numerator denominator)

PRObability of a BOOLean. If no arguments are given, returns #t 1/2 of the time, otherwise takes two integers, numerator and denominator, and returns #t numerator/denominator of the time. Throws an error if denominator is 0. If (>= (/ numerator denominator) 1) probool always returns true. If numerator is 0 probool always returns false.

Example:
(def val0 (probool))
(test::assert-true (or (= #t val0) (= nil val0)))
(def val1 (probool 17 42))
(test::assert-true (or (= #t val1) (= nil val1)))
(test::assert-true (probool 1 1))
(test::assert-false (probool 0 42))
(test::assert-error-msg (probool 0 0) "Denominator can not be zero")
(test::assert-error-msg (probool 0 0 0) "Expected zero or two numbers")


random Type: Function
root::random Usage: (random), (random limit)

Returns non-negative number less than limit and of the same type as limit.

Example:
(def rand-int (random 100))
(test::assert-true (and (> rand-int 0) (< rand-int 100))
(def rand-float (random 1.0))
(test::assert-true (and (> rand-float 0) (< rand-float 1)))
(test::assert-error-msg (random -1) "Expected positive integer")
(test::assert-error-msg (random 1 2) "Expected zero or one integers")


random-str Type: Function
root::random-str Usage: (random-str str-length [char-set])

Takes a positive integer, str-length, and one of :hex, :ascii, :alnum, or a string. Returns random string of provided str-length composed of second argument, :hex results in random hex string, :ascii results in random string of all printable ascii characters, :alnum results in random string of all alphanumeric characters, and providing a string results in a random string composed by sampling input.

Example:
(test::assert-error-msg (random-str) "random-str: Missing required argument, see (doc 'random-str) for usage.")
(test::assert-error-msg (random-str -1) "Expected positive number")
(test::assert-error-msg (random-str 10) "random-str: Missing required argument, see (doc 'random-str) for usage.")
(test::assert-equal 100 (length (random-str 10 :hex))
(test::assert-true (str-contains "⚙" (random-str 42 "⚙"))
(test::assert-equal 19 (length (random-str 19 :ascii)
(test::assert-equal 91 (length (random-str 91 :alnum)


Regex forms

make-regex Type: Function
root::make-regex Usage: (make-regex regex) -> Regex

Given a valid regex string, return a sl-sh Regex. The syntax for regular expressions in sl-sh is borrowed from the Rust regex library and is specified here.

Example:
(test::assert-equal "Regex" (type (make-regex ".*")))


re-color Type: Function
root::re-color Usage: (re-color regex string) -> t/nil

Given a regex and a string, colorize the portions of string that match regex, giving unique values unique colors. Colors are chosen deterministically based on the hash of the capture group’s value. If no capture groups are provided the whole regex is colorized uniquely based on its value. Overlapping capture groups are not supported. The regex argument can either be a regex string or a regex type obtained from make-regex. An optional third keyword argument is accepted, :default, or :unique.

  • :default preserves the default color behavior
  • :unique tries to give unique capture group’s values unique colors. (see example for more information). </span>
Example:
(test::assert-equal
(str "This c" (fg-color-rgb 35 98 130) "onnection takes on" shell::*fg-default*)
(re-color (make-regex "is c(.*)") "This connection takes on"))
(def simple-time-regex (make-regex "(\d{2}):(\d{2})"))
(test::assert-equal
(str (fg-color-rgb 234 27 39) "11" shell::*fg-default* ":" (fg-color-rgb 234 27 39) "11" shell::*fg-default*)
(re-color "(\d{2}):(\d{2})" "11:11"))
(test::assert-equal
(str (fg-color-rgb 234 27 39) "11" shell::*fg-default* ":" (fg-color-rgb 234 27 39) "11" shell::*fg-default*)
(re-color "(\d{2}):(\d{2})" "11:11" :default))
(test::assert-equal
(str (fg-color-rgb 234 27 39) "11" shell::*fg-default* ":" (fg-color-rgb 245 141 19) "11" shell::*fg-default*)
(re-color "(\d{2}):(\d{2})" "11:11" :unique))


re-find Type: Function
root::re-find Usage: (re-find regex string) -> #([String, ..])

Given a regex and a string, find the first matching occurrence of regex in string and return a vector of capture groups. The 0th element of the vector is always a string of the whole match. If N capture groups are provided, the Nth group’s value is placed in the Nth element of the vector, where N is one indexed. The regex argument can either be a regex string or a regex type obtained from make-regex.

Example:
(def found-capture (re-find (make-regex "(\d{4})-(\d{2})-(\d{2})") "2020-12-20 and then again on 2021-12-18 but not on 2020-11-20"))
(test::assert-equal 4 (length found-capture))
(test::assert-equal '#("2020-12-20" "2020" "12" "20") found-capture))
(def found (re-find "\d{4}-\d{2}-\d{2}" "2020-12-20 and then again on 2021-12-18 but not on 2020-11-20"))
(test::assert-equal 1 (length found))
(test::assert-equal '#("2020-12-20") found))
(def found-none (re-find "\d{40}-\d{2}-\d{2}" "2020-12-20 and then again on 2021-12-18 but not on 2020-11-20"))
(test::assert-equal '#() found-none)


re-find-all Type: Function
root::re-find-all Usage: (re-find-all regex string) -> #(#([String, ..])..)

Given a regex and a string, find all matching occurrences of regex in string and return a vector of a vector of capture groups. The 0th element of each nested vector is always a string of the whole match. If N capture groups are provided, the Nth group’s value is placed in the Nth element of its respective match vector, where N is one indexed. The regex argument can either be a regex string or a regex type obtained from make-regex.

Example:
(def found (re-find-all (make-regex "(\d{4})-(\d{2})-(\d{2})") "2020-12-20 and then again on 2021-12-18 but not on 2020-11-20"))
(test::assert-equal 3 (length found))
(test::assert-equal '#("2020-12-20" "2020" "12" "20") (vec-nth found 0))
(test::assert-equal '#("2021-12-18" "2021" "12" "18") (vec-nth found 1))
(test::assert-equal '#("2020-11-20" "2020" "11" "20") (vec-nth found 2))
(def found-one (re-find-all "(\d{4})-(\d{2})-(\d{2})" "2020-12-20 and then again on"))
(test::assert-equal 1 (length found-one))
(test::assert-equal '#("2020-12-20" "2020" "12" "20") (vec-nth found-one 0))
(def found-none (re-find-all "(\d{40})-(\d{2})-(\d{2})" "2020-12-20 and then again on"))
(test::assert-equal '#() found-none)


re-match Type: Function
root::re-match Usage: (re-match regex string) -> boolean?

Given a regex and a string, return true if regex is found in string, and return false otherwise. The regex argument can either be a regex string or a regex type obtained from make-regex.

Example:
(test::assert-true
(re-match (make-regex "(\d{4})-(\d{2})-(\d{2})") "2020-12-20 and then again on 2021-12-18 but not on 2020-11-20"))
(test::assert-false
(re-match "(\d{4})-(\d{2})-(\d{20})" "2020-12-20 and then again on 2021-12-18 but not on 2020-11-20"))


re-replace Type: Function
root::re-replace Usage: (re-replace regex string replacement) -> String

Given a regex, a string, and a replacement string, return a modified version of string where all occurrences of regex are edited according to the replacement syntax. The replacement string syntax is borrowed from the Rust regex library and is specified here. The regex argument can either be a regex string or a regex type obtained from make-regex.

Example:
(test::assert-equal
"Thon connection takes on"
(re-replace (make-regex "This") "This connection takes on" "Thon"))
(test::assert-equal
"Thon connection takes"
(re-replace "is (.*) (.*)" "This connection takes on" "\$2 \$1"))
(test::assert-equal
"10-20-2020 and then again on 12-18-2021 but not on 11-20-2020"
(re-replace (make-regex "(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})") "2020-10-20 and then again on 2021-12-18 but not on 2020-11-20" "\$m-\$d-\$y"))


Root forms

*read-table* Type: HashMap
root::*read-table* Usage: (print *read-table*)

Symbol that contains the current read table.

Example:
;(hash-set! *read-table* #\$ 'shell-read::shell-read)
#t


*read-table-terminal* Type: HashMap
root::*read-table-terminal* Usage: (print *read-table-terminal*)

Symbol that contains the current terminal read table.

Example:
;(hash-set! *read-table-terminal* #\] 'nop-read)
#t


*string-read-table* Type: HashMap
root::*string-read-table* Usage: (print *string-read-table*)

Symbol that contains the current string read table.

Example:
;(hash-set! *string-read-table* #\$ 'shell-read::shell-read)
#t


Scripting forms

*load-path* Type: Vector
root::*load-path* Usage: (set '*load-path* '("/path/one" "/path/two"))

Set the a list of paths to search for loading scripts with the load form.

Example:
;(set '*load-path '("/path"))
;(load "script-in-path")
t


load Type: Function
root::load Usage: (load path) -> [last form value]

Read and eval a file (from path- a string).

Example:
(def test-load-one nil)
(def test-load-two nil)
(def test-load-fn (open "/tmp/slsh-test-load.testing" :create :truncate))
(write-line test-load-fn "(set! test-load-one \"LOAD TEST\") '(1 2 3)")
(close test-load-fn)
(set! test-load-two (load "/tmp/slsh-test-load.testing"))
(test::assert-equal "LOAD TEST" test-load-one)
(test::assert-equal '(1 2 3) test-load-two)


mkli Type: Lambda
shell::mkli Usage: (mkli filepath [namespace] [body])

“make lisp”.creates a sl-sh shell script. given a file, a namespace (optional 2nd arg), and a string to populate as the body (optional 3rd arg), make a canonincal blank sl-sh script complete with all the relevant imports, and boilerplate namespace code taken care of to speed up development. It is recommended all calls to load are done at the top of the file (before the calls to ns-enter or ns-create, in case a library sl-sh script calls a library sl-sh script that created a namespace and forgot to call ns-pop. This ensures the exported symbols for the first library’s scripts namespace are importable in the executing script’s namespace. All calls to ns-import happen after a ns is created and entered so the current namespace is the namespace that houses all the imported symbols. ns-export must be called before ns-pop so the appropriate symbols are associated namespace, the one in which the symbols were created.

Example:
(defn test-file (code file)
(let ((tmp (open file :read)))
(assert-equal
code
(read-all tmp))
(close tmp))
(with-temp (fn (tmp-dir)
(let ((tmp0 (get-temp-file tmp-dir))
(tmp1 (get-temp-file tmp-dir))
(tmp2 (get-temp-file tmp-dir)))
(mkli tmp0 'mytest (println "hello test"))
(test-file
'#((ns-push 'mytest)
(ns-import 'shell)
(println "hello test")
(ns-auto-export 'mytest)
(ns-pop))
tmp0)
(mkli tmp1 'mytest)
(test-file
'#((ns-push 'mytest)
(ns-import 'shell)
(ns-auto-export 'mytest)
(ns-pop))
tmp1)
(mkli tmp2)
(test-file
'#(ns-import 'shell)
tmp2))))


Sequence forms

These macros will work on either a vector or a pair made into a proper list (cons list). Use these in preference to the vector/list specific versions when possible (i.e. first vs car). NOTE: list on this table can be a vector or a list.

butlast Type: Lambda
root::butlast Usage: (butlast obj)

Produces the provided list minus the last element. Nil if the list is empty or one element.

Example:
(assert-equal '(1 2) (butlast '(1 2 3)))
(assert-equal '(1 2) (butlast '#(1 2 3)))
(assert-equal nil (butlast '(1)))
(assert-equal nil (butlast '#(1)))
(assert-equal nil (butlast '()))
(assert-equal nil (butlast nil))
(assert-equal nil (butlast '#()))


collect-copy Type: Lambda
root::collect-copy Usage: (collect-copy seq)

Produces a copy of the provided list (copy has same type as the parameter).

Example:
(def test-colcl '(1 2 3))
(assert-true (list? test-colcl))
(def test-colcl2 (collect-copy test-colcl))
(assert-true (list? test-colcl2))
(assert-equal test-colcl test-colcl2)
(def test-colcv '#(1 2 3))
(assert-true (vec? test-colcv))
(def test-colcv2 (collect-copy test-colcv))
(assert-true (vec? test-colcv2))
(assert-equal test-colcv test-colcv2)


empty-seq? Type: Lambda
root::empty-seq? Usage: (empty-seq? obj) -> t/nil

empty-seq? returns true if a list or vector is empty and false/nil otherwise. If a non list or non vector is passed in it returns nil.

Example:
(test::assert-false (empty-seq? '(1 2 3)))
(test::assert-false (empty-seq? '#(1 2 3)))
(test::assert-true (empty-seq? '()))
(test::assert-true (empty-seq? '#()))
(test::assert-false (empty-seq? "aaa"))
(test::assert-false (empty-seq? 1))


first Type: Lambda
root::first Usage: (first obj)

Produces the first element of the provided list or vector. Nil if the list/vector is nil/empty. Note this is like car that works for lists and vectors.

Example:
(assert-equal 1 (first '(1 2 3)))
(assert-equal 1 (first '#(1 2 3)))
(assert-equal nil (first '()))
(assert-equal nil (first nil))
(assert-equal nil (first '#()))


in? Type: Lambda
root::in? Usage: (in? seq-to-search item-to-match)

Takes a seq? that is not an empty-seq? and returns true if the second argument is is in list, false otherwise.

Example:
(let ((vowels-list (list 'a 'e 'i 'o 'u)))
(assert-true (in? vowels-list 'u))
(assert-false (in? vowels-list 'c))
(assert-true (in? (list (list)) (list)))
(assert-false (in? 8 18)))


last Type: Lambda
root::last Usage: (last obj)

Produces the last element in a list or vector. Nil if the list/vector is empty.

Example:
(assert-equal 3 (last '(1 2 3)))
(assert-equal 3 (last '#(1 2 3)))
(assert-equal nil (last '()))
(assert-equal nil (last nil))
(assert-equal nil (last '#()))


non-empty-seq? Type: Lambda
root::non-empty-seq? Usage: (non-empty-seq? obj) -> t/nil

non-empty-seq? returns true if a list or vector is not empty and false/nil otherwise. If a non list or non vector is passed in it returns nil.

Example:
(test::assert-true (non-empty-seq? '(1 2 3)))
(test::assert-true (non-empty-seq? '#(1 2 3)))
(test::assert-false (non-empty-seq? '()))
(test::assert-false (non-empty-seq? '#()))
(test::assert-false (non-empty-seq? "aaa"))
(test::assert-false (non-empty-seq? 1))


qsort Type: Lambda
root::qsort Usage: (qsort sequence comp-lambda?) -> [sorted vector]

Sort a sequence using the quick sort algorithm. Returns a vector of the sorted sequence. The comp-lambda argument is optional, if provided it should be a lambda or builtin that takes two arguments and return t or nil (it is the compare function for the sort). Defaults to < if not provided.

Example:
(test::assert-equal '(1 2 3) (qsort '(2 3 1)))
(test::assert-equal '(1 2 3) (qsort '#(2 3 1)))
(test::assert-equal '(3 2 1) (qsort '(2 3 1) >))
(test::assert-equal '(3 2 1) (qsort '#(2 3 1) (fn (a b) (< b a))))
(test::assert-equal '("aaa" "aab" "aba" "baa" "bab" "ccc")
(qsort '("aaa" "aab" "aba" "baa" "bab" "ccc")))
(test::assert-equal '("aaa" "aab" "aba" "baa" "bab" "ccc")
(qsort '("ccc" "bab" "baa" "aba" "aab" "aaa")))
(test::assert-equal '("aaa" "aab" "aba" "baa" "bab" "ccc")
(qsort '("aba" "bab" "aab" "ccc" "baa" "aaa")))
(test::assert-equal '("ccc" "bab" "baa" "aba" "aab" "aaa")
(qsort '("aba" "bab" "aab" "ccc" "baa" "aaa") >))
(test::assert-equal '("ccc" "bab" "baa" "aba" "aab" "aaa")
(qsort '("aba" "bab" "aab" "ccc" "baa" "aaa") (fn (a b) (> a b))))
(test::assert-equal '() (qsort '()))
(test::assert-equal '() (qsort '#()))
(test::assert-equal '#() (qsort '()))
(test::assert-equal '#() (qsort '#()))


rest Type: Lambda
root::rest Usage: (rest obj)

Produces the provided list or vector minus the first element. Nil if the list/vector is nil/empty or one element. Note this is like cdr that works for lists and vectors. This calls vec-slice to create a new vector when called with a vector (i.e. is much more efficient with lists).

Example:
(assert-equal '(2 3) (rest '(1 2 3)))
(assert-equal '(2 3) (rest '#(1 2 3)))
(assert-equal nil (rest '(1)))
(assert-equal nil (rest '#(1)))
(assert-equal nil (rest '()))
(assert-equal nil (rest nil))
(assert-equal nil (rest '#()))


seq-for Type: Macro
root::seq-for Usage: (seq-for bind in items body)

Loops over each element in a sequence. Simple version that works with lists and vectors, use iterator::for in general.

Example:
(def i 0)
(seq-for x in '(1 2 3 4 5 6) (set! i (+ 1 i)))
(assert-equal 6 i)


seq? Type: Lambda
root::seq? Usage: (seq? expression) -> t/nil

True if expression is a list or vector, nil otherwise.

Example:
(test::assert-true (seq? '(1 2 3)))
(test::assert-true (seq? '#(1 2 3)))
(test::assert-true (seq? '()))
(test::assert-true (seq? '#()))
(test::assert-false (seq? "aaa"))
(test::assert-false (seq? 1))


setnth! Type: Lambda
root::setnth! Usage: (setnth! idx obj sequence)

Sets idx item in the vector or list to obj, produces nil or errors on invalid input. This is destructive! Because vectors support indexing and lists do not, this is a much faster operation for a vector (uses builtin vec-set! on input of type vector). Return the list or vector that was modified.

Example:
(def vctr (vec 0 1 2 3))
(def vec-copy (collect-copy vctr))
(setnth! 0 -5 vctr)
(setnth! 1 -400000 vctr)
(setnth! 2 -402202 vctr)
(setnth! 3 -30000 vctr)
(assert-not-equal vec-copy vctr)
(setnth! 0 -4 vctr)
(setnth! 1 -3 vctr)
(setnth! 2 -2 vctr)
(setnth! 3 -1 vctr)
(assert-equal (list -4 -3 -2 -1) vctr)
(assert-equal '(1 5 3) (setnth! 1 5 '#(1 2 3)) " Vector check")
(assert-error (setnth! 0 1 '#()))
(assert-error (setnth! 0 1 (vec)))
(def lst (list 0 1 2 3))
(def list-copy (collect-copy lst))
(setnth! 0 -4 lst)
(setnth! 1 -3 lst)
(setnth! 2 -2 lst)
(setnth! 3 -1 lst)
(assert-not-equal list-copy lst)
(setnth! 0 -4 lst)
(setnth! 1 -3 lst)
(setnth! 2 -2 lst)
(setnth! 3 -1 lst)
(assert-equal (list -4 -3 -2 -1) lst)
(assert-equal '(1 5 3) (setnth! 1 5 '(1 2 3)) " List check")
(assert-error (setnth! 0 1 '()))
(assert-error (setnth! 0 1 (list)))


Shell forms

Forms to do shell operations like file tests, pipes, redirects, etc.

*stderr* Type: File
root::*stderr* Usage: (write-line *stderr*)

File that connects to standard error by default. Can be used in place of a write file object in any form that takes one. Used as the default for eprint and eprintln.

Example:
; Use a file for stderr for test.
(dyn *stderr* (open "/tmp/sl-sh.stderr.test" :create :truncate) (do (write-line *stderr* "Test Error") (close *stderr*)))
(test::assert-equal "Test Error
" (read-line (open "/tmp/sl-sh.stderr.test" :read)))


*stdin* Type: File
root::*stdin* Usage: (read-line *stdin*)

File that connects to standard in by default. Can be used in place of a read file object in any form that takes one.

Example:
(def stdin-test (open "/tmp/sl-sh.stdin.test" :create :truncate))
(write-line stdin-test "Test line")
(close stdin-test)
; Use a file for stdin for test.
(dyn *stdin* (open "/tmp/sl-sh.stdin.test" :read) (do (test::assert-equal "Test line
" (read-line *stdin*)) (close *stdin*)))


*stdout* Type: File
root::*stdout* Usage: (write-line *stdout*)

File that connects to standard out by default. Can be used in place of a write file object in any form that takes one. Used as the default for print and println.

Example:
; Use a file for stdout for test.
(dyn *stdout* (open "/tmp/sl-sh.stdout.test" :create :truncate) (do (write-line *stdout* "Test out") (close *stdout*)))
(test::assert-equal "Test out
" (read-line (open "/tmp/sl-sh.stdout.test" :read)))


alias Type: Macro
shell::alias Usage: (alias name body) or (alias name docstring body)

Create an alias, intended to be used with executables not lisp code (use defn for that).

Example:
(shell::alias xx-echo1 (echo arg1))
(shell::alias xx-echo2 "Dummy doc string" (echo))
(let ((file-name (str (temp-dir)"/alias-test.out"))
(topen))
(out> file-name (xx-echo1 "stdout redir one1"))
(out>> file-name (xx-echo2 "stdout redir one2"))
(set! topen (open file-name :read))
(test::assert-equal "arg1 stdout redir one1\n" (read-line topen))
(test::assert-equal "stdout redir one2\n" (read-line topen))
(test::assert-false (read-line topen))
(close topen))


alias? Type: Lambda
shell::alias? Usage: (alias? name)

Provides boolean value confirming or denying given alias’ presence in set of registered aliases.

Example:
(def xx-echo-not-alias #t)
(test::assert-false (alias? 'xx-echo-not-alias))
(test::assert-false (alias? 'xx-echo))
(shell::alias xx-echo (echo -en))
(test::assert-true (alias? 'xx-echo))
(unalias xx-echo)
(test::assert-false (alias? 'xx-echo))


bg-color-rgb Type: Lambda
shell::bg-color-rgb Usage: (bg-color-rgb red-val green-val blue-val)

Set the background color to the desired rgb where each arg is an integer between 0 and 255 inclusive.

Example:
(test::assert-equal "" (bg-color-rgb 128 128 128))
(test::assert-equal "" (bg-color-rgb 255 255 255))
(test::assert-equal "" (bg-color-rgb 255 0 0))
(test::assert-equal "" (bg-color-rgb 0 255 0))
(test::assert-equal "" (bg-color-rgb 0 0 255))
(test::assert-equal "" (bg-color-rgb 0 0 0))


clear-dirs Type: Lambda
shell::clear-dirs Usage: (clear-dirs)

Clears the directory stack.

Example:
(clear-dirs)
(def cur-test-path (get-env PWD))
(test::assert-equal '() (get-dirs))
(pushd "/tmp")
(def cur-test-path2 (get-env PWD))
(test::assert-equal `(,cur-test-path) (get-dirs))
(pushd (str-trim cur-test-path))
(test::assert-equal `(,cur-test-path ,cur-test-path2) (get-dirs))
(clear-dirs)
(test::assert-equal '() (get-dirs))


dirs Type: Lambda
shell::dirs Usage: (dirs)

List the directory stack.

Example:
(clear-dirs)
(def cur-test-path (get-env PWD))
(dyn *stdout* (open "/tmp/sl-sh.dirs.test" :create :truncate) (dirs))
(test::assert-equal nil (read-line (open "/tmp/sl-sh.dirs.test" :read)))
(pushd "/tmp")
(def cur-test-path2 (get-env PWD))
(dyn *stdout* (open "/tmp/sl-sh.dirs.test" :create :truncate) (dirs))
(test::assert-equal cur-test-path (str-trim (read-line (open "/tmp/sl-sh.dirs.test" :read))))
(pushd (str-trim cur-test-path))
(dyn *stdout* (open "/tmp/sl-sh.dirs.test" :create :truncate) (dirs))
(def test-dirs-file (open "/tmp/sl-sh.dirs.test" :read))
(test::assert-equal cur-test-path (str-trim (read-line test-dirs-file)))
(test::assert-equal cur-test-path2 (str-trim (read-line test-dirs-file)))
(close test-dirs-file)
(popd)
(dyn *stdout* (open "/tmp/sl-sh.dirs.test" :create :truncate) (dirs))
(test::assert-equal cur-test-path (str-trim (read-line (open "/tmp/sl-sh.dirs.test" :read))))
(popd)
(dyn *stdout* (open "/tmp/sl-sh.dirs.test" :create :truncate) (dirs))
(test::assert-equal nil (read-line (open "/tmp/sl-sh.dirs.test" :read)))


epoch Type: Function
root::epoch Usage: (epoch)

Prints system time in milliseconds.

Example:
;(epoch)
#t


err> Type: Macro
shell::err> Usage: (err> file body)

Redirect stderr to file, truncate the file first.

Example:
(err> "/tmp/sl-sh.err>.test" (eprintln "stderr redir one"))
(def topen (open "/tmp/sl-sh.err>.test" :read))
(test::assert-equal "stderr redir one
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)
(err> "/tmp/sl-sh.err>.test" (eprintln "stderr redir two"))
(def topen (open "/tmp/sl-sh.err>.test" :read))
(test::assert-equal "stderr redir two
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)


err>> Type: Macro
shell::err>> Usage: (err>> file body)

Redirect stderr to file, append the output.

Example:
(err> "/tmp/sl-sh.err>>.test" (eprintln "stderr redir one"))
(def topen (open "/tmp/sl-sh.err>>.test" :read))
(test::assert-equal "stderr redir one
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)
(err>> "/tmp/sl-sh.err>>.test" (eprintln "stderr redir two"))
(def topen (open "/tmp/sl-sh.err>>.test" :read))
(test::assert-equal "stderr redir one
" (read-line topen))
(test::assert-equal "stderr redir two
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)


err>null Type: Macro
shell::err>null Usage: (err>null body)

Redirect stderr to null (/dev/null equivelent).

Example:
(err> "/tmp/sl-sh.err>null.test" (do (eprintln "stderr redir one")(err>null (eprintln "stdnull redir one"))))
(def topen (open "/tmp/sl-sh.err>null.test" :read))
(test::assert-equal "stderr redir one
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)


fc Type: Lambda
shell::fc Usage: (fc)

Put the contents of the last command into a temporary file (temp-dir), and open the temporary file in the text editor, If the editor returns with an error code of 0 the contents of the temporary file are executed. fc can be used in succession and the contents of the temporary file are saved to the sl-sh history.

fg-color-rgb Type: Lambda
shell::fg-color-rgb Usage: (fg-color-rgb red-val green-val blue-val)

Set the foreground color to the desired rgb where each arg is an integer between 0 and 255 inclusive.

Example:
(test::assert-equal "" (fg-color-rgb 128 128 128))
(test::assert-equal "" (fg-color-rgb 255 255 255))
(test::assert-equal "" (fg-color-rgb 255 0 0))
(test::assert-equal "" (fg-color-rgb 0 255 0))
(test::assert-equal "" (fg-color-rgb 0 0 255))
(test::assert-equal "" (fg-color-rgb 0 0 0))


get-dirs Type: Lambda
shell::get-dirs Usage: (get-dirs)

Return the vector of directories.

Example:
(clear-dirs)
(def cur-test-path (get-env PWD))
(test::assert-equal '() (get-dirs))
(pushd "/tmp")
(def cur-test-path2 (get-env PWD))
(test::assert-equal `(,cur-test-path) (get-dirs))
(pushd (str-trim cur-test-path))
(test::assert-equal `(,cur-test-path ,cur-test-path2) (get-dirs))
(popd)
(test::assert-equal `(,cur-test-path) (get-dirs))
(popd)
(test::assert-equal '() (get-dirs))


getopts Type: Lambda
shell::getopts Usage: (getopts options-map args)

Getopts takes a hash map and a vector of args and returns a hash map with all the values extracted from the args and bound to the corresponding keys in the provided hash map. Support for automatically generating documentation is available with helper function getopts-help. Take this example script: sample-getopts.lisp

#!/usr/bin/env sl-sh
(println "Passing: " args " to getopts")
;; getopts is given a hash map with one key, :-m, that corresponds to the flag,
;; -m, that it configures.
(def *sample-getopts-bindings*
(getopts
(make-hash
(list (join
:-m
(make-hash '((:arity . 1)
(:default . 0)
(:type . :int?))))))
args))
(println "The binding for -m is: " (hash-get *sample-getopts-bindings* :-m) "of type " (type (hash-get *sample-getopts-bindings* :-m)))

Running the script with one argument to the -m flag yields:

/sample-getopts.lisp -m 7
Passing: #("-m" "7") to getopts
The binding for -m is 7 of type Int

The hash map for the key :-m showcases the configuration keys that exist for each flag: arity, :default, and :type. :arity specifies that the -m flag will take one argument. :default specifies the bindng for :-m should be 0 if the -m flag is not seen in args. :type :int? specifies that the binding should be of that type, in this case int?. Running the script again with no -m flag yields:

/sample-getopts.lisp
Passing: #() to getopts
The binding for -m is 0 of type Int

Demonstrating the :default binding of 0 for the symbol :-m since the -m flag was not provided as an argument to the script. Configuration keys for flags:

  • :arity (optional) Defaults to 0. If the arity is 0 the returned binding will be #t or nil. Can be any integer. The integer value for the :arity corresponds to the number of arguments getopts will enforce for this flag, if the number of arguments provided to the flag is not equal to the specified arity an error is thrown.
  • :default (optional) Use this as a default if the given flag is not provided at execution time.
  • :type (optional) Specify a type for every provided argument for the given flag. Types can be any of: (“list?” “macro?” “fs-dir?” “symbol?” “fs-exists?” “int?” “hash?” “vec?” “float?” “lambda?” “falsey?” “string?” “fs-file?” “char?”) Rules for flags:
  • Flags can be single character: -m -n -c etc.
  • Flags of a single single character with arity 0 can be adjacent without the need for additional dashes: -mnc
  • Multiple flags of a single character with arity 0 can precede a flag of a single character with arity N as long as said character appears last: -mne “foo”
  • Flags can be multi-character as long as they are preceded by two dashes: –multi-char-arg </span>
Example:
;See tests/getopts.lisp
#t


getopts-help Type: Lambda
shell::getopts-help Usage: (getopts-help bindings)

Companion function to getopts, call this function in the docstring of any function that relies on getopts. getopts-help takes as an argument the same bindings hash map that getopts does, and returns the documentation for those getopts settings. getopts-help optionally supports a :doc keyword for each command key. The value of doc is included in the resultant doc string getopts-help returns.

Example:
;;; The following represents a full example usage of getopts
;;; with documentation generated in the doc string of the function that uses
;;; getopts:
(def getopts-bindings
(make-hash
(list
(def getopts-help-bindings
(make-hash
(list (join
:-m
(make-hash '((:arity . 1)
(:default . 0)
(:type . :int?)
(:doc "this is displayed as
two indented lines."))))
(join
:-b
(make-hash '((:doc "this opts doc for -b
goes on two lines!"))))
(join
:-a
(make-hash '((:arity . 1)
(:doc "this doc is for -a."))))
(join
:-k
(make-hash '((:arity . 1)
(:type . :int?)))))))
(test::assert-equal
(str-split :whitespace (getopts-help getopts-help-bindings))
(str-split :whitespace (str-push! (str) # "-a" # "arity 1" # "this doc is for -a." # "-b" # "arity 0" # "this opts doc for -b" # "goes on two lines!" # "-k" # "arity 1" # "required type :int?" # "-m" # "arity 1" # "default value 0" # "required type :int?" # "this is displayed as" # "two indented lines.")))


history-context Type: Function
root::history-context Usage: (history-context :context_id context-string) -> nil

Sets the history context for searches. Usually the current path but can be any string. Pass nil to set it to nothing.

Example:
;(history-context :repl "/home")
#t


history-empty? Type: Function
root::history-empty? Usage: (history-empty? :context_id) -> t/nil

Returns true if history for context_id is empty, nil otherwise.

Example:
;(history-empty? :repl)
#t


history-length Type: Function
root::history-length Usage: (history-length :context_id) -> int

Returns the number of history items for the given context.

Example:
;(history-length :repl)
#t


history-nth Type: Function
root::history-nth Usage: (history-nth :context_id nth) -> String

Returns the history at index nth (the newest is 0).

Example:
;(history-nth :repl 0)
#t


history-push Type: Function
root::history-push Usage: (history-push :context_id string) -> nil/t

Pushes string onto the history for the prompt context :context_id. Returns true on success or nil on failure.

Example:
;(history-push :repl "Some command")
#t


history-push-throwaway Type: Function
root::history-push-throwaway Usage: (history-push-throwaway :context_id string) -> nil/t

Pushes string onto the history for the prompt context :context_id. A throwaway item will will only persist until the next command is read (use it to allow editing of failed commands without them going into history). Returns true on success or nil on failure.

Example:
;(history-push-throwaway :repl "Some broken command")
#t


let-env Type: Macro
shell::let-env Usage: (let-env vals &rest let_body)

Like let but sets environment variables that are reset after the macro finishes.

Example:
(test::assert-equal "" $LET-ENV-TEST-VAR-NOT-HERE)
(let-env ((LET-ENV-TEST-VAR-NOT-HERE "here"))
(test::assert-equal "here" $LET-ENV-TEST-VAR-NOT-HERE))
(test::assert-equal "" $LET-ENV-TEST-VAR-NOT-HERE)


out-err> Type: Macro
shell::out-err> Usage: (out-err> file body)

Redirect both stdout and stderr to the same file, truncate the file first.

Example:
(out-err> "/tmp/sl-sh.out-err>.test" (do (println "stdout redir one")(eprintln "stderr redir one")))
(def topen (open "/tmp/sl-sh.out-err>.test" :read))
(test::assert-equal "stdout redir one
" (read-line topen))
(test::assert-equal "stderr redir one
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)
(out-err> "/tmp/sl-sh.out-err>.test" (do (syscall 'echo "stdout echo redir one")(eprintln "stderr redir one")))
(def topen (open "/tmp/sl-sh.out-err>.test" :read))
(test::assert-equal "stdout echo redir one
" (read-line topen))
(test::assert-equal "stderr redir one
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)
(out-err> "/tmp/sl-sh.out-err>.test" (do (println "stdout redir two")(eprintln "stderr redir two")))
(def topen (open "/tmp/sl-sh.out-err>.test" :read))
(test::assert-equal "stdout redir two
" (read-line topen))
(test::assert-equal "stderr redir two
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)


out-err>> Type: Macro
shell::out-err>> Usage: (out-err>> file body)

Redirect both stdout and stderr to the same file, append the output.

Example:
(out-err> "/tmp/sl-sh.out-err>>.test" (do (println "stdout redir one")(eprintln "stderr redir one")))
(def topen (open "/tmp/sl-sh.out-err>>.test" :read))
(test::assert-equal "stdout redir one
" (read-line topen))
(test::assert-equal "stderr redir one
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)
(out-err>> "/tmp/sl-sh.out-err>>.test" (do (println "stdout redir two")(eprintln "stderr redir two")))
(def topen (open "/tmp/sl-sh.out-err>>.test" :read))
(test::assert-equal "stdout redir one
" (read-line topen))
(test::assert-equal "stderr redir one
" (read-line topen))
(test::assert-equal "stdout redir two
" (read-line topen))
(test::assert-equal "stderr redir two
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)


out-err>null Type: Macro
shell::out-err>null Usage: (out-err>null body)

Redirect both stdout and stderr to null (/dev/null equivelent).

Example:
(out-err> "/tmp/sl-sh.out-err>null.test" (do
(println "stdout redir one")
(eprintln "stderr redir one")
(out-err>null (do
(println "stdnull redir one")
(eprintln "stdnull redir one")))))
(def topen (open "/tmp/sl-sh.out-err>null.test" :read))
(test::assert-equal "stdout redir one
" (read-line topen))
(test::assert-equal "stderr redir one
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)


out> Type: Macro
shell::out> Usage: (out> file body)

Redirect stdout to file, truncate the file first.

Example:
(out> "/tmp/sl-sh.out>.test" (syscall 'echo "stdout redir one"))
(def topen (open "/tmp/sl-sh.out>.test" :read))
(test::assert-equal "stdout redir one
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)
(out> "/tmp/sl-sh.out>.test" (syscall 'echo "stdout redir two"))
(def topen (open "/tmp/sl-sh.out>.test" :read))
(test::assert-equal "stdout redir two
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)


out>> Type: Macro
shell::out>> Usage: (out>> file body)

Redirect stdout to file, append the output.

Example:
(out> "/tmp/sl-sh.out>>.test" (syscall 'echo "stdout redir one"))
(def topen (open "/tmp/sl-sh.out>>.test" :read))
(test::assert-equal "stdout redir one
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)
(out>> "/tmp/sl-sh.out>>.test" (syscall 'echo "stdout redir two"))
(def topen (open "/tmp/sl-sh.out>>.test" :read))
(test::assert-equal "stdout redir one
" (read-line topen))
(test::assert-equal "stdout redir two
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)


out>null Type: Macro
shell::out>null Usage: (out>null body)

Redirect stdout to null (/dev/null equivelent).

Example:
(out> "/tmp/sl-sh.out>null.test" (do (println "stdout redir one")(out>null (println "stdnull redir one"))))
(def topen (open "/tmp/sl-sh.out>null.test" :read))
(test::assert-equal "stdout redir one
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)


popd Type: Lambda
shell::popd Usage: (popd)

Pop first directory from directory stack and change to it.

Example:
(def cur-test-path (get-env PWD))
(pushd "/tmp")
(def cur-test-path2 (get-env PWD))
(assert-equal cur-test-path2 (get-env PWD))
(popd)
(assert-equal cur-test-path (get-env PWD))


prompt Type: Function
root::prompt Usage: (prompt string) -> string

Starts an interactive prompt (like the repl prompt) with the supplied prompt and returns the input string.

Example:
;(def input-string (prompt "prompt> "))
#t


pushd Type: Lambda
shell::pushd Usage: (pushd dir)

Push current directory on the directory stack and change to new directory.

Example:
(def cur-test-path (get-env PWD))
(pushd "/tmp")
(def cur-test-path2 (get-env PWD))
(assert-equal cur-test-path2 (get-env PWD))
(popd)
(assert-equal cur-test-path (get-env PWD))


register-alias Type: Lambda
shell::register-alias Usage: (register-alias name)

Registers an alias to the current scope. Useful if unregistering or ability to know whether an alias has been registered is desirable.

set-dirs-max Type: Lambda
shell::set-dirs-max Usage: (set-dirs-max max)

Sets the max number of directories to save in the stack.

Example:
(clear-dirs)
(def cur-test-path (get-env PWD))
(pushd "/tmp")
(def cur-test-path2 (get-env PWD))
(pushd (str-trim cur-test-path))
(pushd "/tmp")
(pushd (str-trim cur-test-path))
(test::assert-equal `(,cur-test-path ,cur-test-path2 ,cur-test-path ,cur-test-path2) (get-dirs))
(clear-dirs)
(set-dirs-max 3)
(pushd "/tmp")
(pushd (str-trim cur-test-path))
(pushd "/tmp")
(pushd (str-trim cur-test-path))
(test::assert-equal `(,cur-test-path2 ,cur-test-path ,cur-test-path2) (get-dirs))


syntax-off Type: Macro
shell::syntax-off Usage: (syntax-off)

Turn off syntax highlighting at the repl.

syntax-on Type: Lambda
shell::syntax-on Usage: (syntax-on)

Turn on syntax highlighting at the repl.

sys-command? Type: Lambda
shell::sys-command? Usage: (sys-command? com)

True if the supplied command is a system command.

Example:
(assert-true (sys-command? "ls"))
(assert-false (sys-command? "rst-not-a-comand-strsnt"))


timer Type: Lambda
shell::timer Usage: (timer)

timer struct Initialize a timer object that can be called repeatedly with :pr-next to return relative time passed since instantiation and time since last called or first instantiated. attribute: start-time private attribute: noop private attribute: cnt private attribute: prev-time private attribute: curr-time private attribute: timer-name private method: :get-next method: :pr-next method: :init

Example:
(def test-timer ((timer) :init "test-timer" nil))
(def timer-str (test-timer :get-next "event0"))
(def timer-str-vec (str-split :whitespace timer-str))
(test::assert-equal "{0}[test-timer-event0]:" (vec-nth timer-str-vec 0))
(test::assert-true (int? (str->int (vec-nth timer-str-vec 1))))
(test::assert-true (int? (str->int (vec-nth timer-str-vec 4))))
(def elapsed (vec-nth timer-str-vec 1))
(def difference (vec-nth timer-str-vec 4))
(test::assert-equal elapsed difference)


unalias Type: Macro
shell::unalias Usage: (unalias name)

Remove an alias. Use this instead of undef to make sure book keeping happens.

Example:
(shell::alias xx-echo (echo))
(let ((file-name (str (temp-dir)"/unalias-test.out"))
(topen))
(out> file-name (xx-echo "stdout redir\none1"))
(set! topen (open file-name :read))
(test::assert-equal "stdout redir\n" (read-line topen))
(test::assert-equal "one1\n" (read-line topen))
(test::assert-false (read-line topen))
(close topen))
(unalias xx-echo)
(test::assert-error (xx-echo "error"))


unregister-alias Type: Lambda
shell::unregister-alias Usage: (unregister-alias name)

Unregisters an alias, removing it from scope.

version Type: Function
root::version Usage: (version)

Produce executable version as string.

Example:
(test::assert-true (string? (version)))


Stats forms

first-quartile Type: Function
stats::first-quartile Usage: (first-quartile number+)

Returns first quartile of distribution of provided arguments.

Example:
(ns-import 'stats)
(test::assert-error-msg (first-quartile) "expected at least one number")
(test::assert-equal 2.5 (first-quartile 10 4 8 7 6 5 9 3 2 1))


max Type: Function
stats::max Usage: (max number+)

Returns maximum of provided arguments.

Example:
(ns-import 'stats)
(test::assert-error-msg (max) "expected at least one number")
(test::assert-equal 11 (max 10 4 8 7 6 5 9 3 2 1 11))


mean Type: Function
stats::mean Usage: (mean number+)

Average a sequence of numbers.

Example:
(ns-import 'stats)
(test::assert-error-msg (mean) "expected at least one number")
(test::assert-equal 5 (mean 5))
(test::assert-equal 7.5 (mean 5 10))
(test::assert-equal 5.5 (mean 1 2 3 4 5 6 7 8 9 10))


median Type: Function
stats::median Usage: (median number+)

Returns median of sequence of numbers.

Example:
(ns-import 'stats)
(test::assert-error-msg (median) "expected at least one number")
(test::assert-equal 5 (median 5))
(test::assert-equal 7.5 (median 10 5))
(test::assert-equal 5.5 (median 10 9 8 7 6 5 4 3 2 1))
(test::assert-equal 6 (median 10 4 8 7 6 5 9 3 2 1 11))


min Type: Function
stats::min Usage: (min number+)

Returns minimum of provided arguments.

Example:
(ns-import 'stats)
(test::assert-error-msg (min) "expected at least one number")
(test::assert-equal 1 (min 10 4 8 7 6 5 9 3 2 1 11))


mode Type: Function
stats::mode Usage: (mode number+)

Returns mode of a sequence of numbers. Since distributions can be multimodal, mode returns a list.

Example:
(ns-import 'stats)
(test::assert-error-msg (mode) "expected at least one number")
(test::assert-equal (list 5) (mode 5))
(test::assert-equal (list 1 3 4 5 6 7 8 9 10) (mode 1 3 4 5 6 7 8 9 10))
(test::assert-equal (list 7.0) (mode 1 7.0 3 4 5 6 7 8 9 10))


std-dev Type: Function
stats::std-dev Usage: (std-dev number+)

Returns standard deviation of a sequence of numbers.

Example:
(ns-import 'stats)
(test::assert-error-msg (std-dev) "expected at least one number")
(test::assert-equal 3.0276503540974917 (std-dev 1 2 3 4 5 6 7 8 9 10))


summary-stats Type: Function
stats::summary-stats Usage: (summary-stats number+)

Returns hash map containing summary statistics and sorted array.

Example:
(ns-import 'stats)
(test::assert-error-msg (summary-stats) "expected at least one number")
(def distr (summary-stats 10 2 9 4 6 5 7 8 3 1))
(test::assert-equal '#(1 2 3 4 5 6 7 8 9 10) (hash-get distr :vec))
(test::assert-equal 5.5 (hash-get distr :med))
(test::assert-equal 10 (hash-get distr :max))
(test::assert-equal 3.0276503540974917 (hash-get distr :sd))
(test::assert-equal 5.5 (hash-get distr :mean))
(test::assert-equal '#(1 2 3 4 5 6 7 8 9 10) (hash-get distr :mode))
(test::assert-equal 1 (hash-get distr :min))
(test::assert-equal 8 (hash-get distr :q3))
(test::assert-equal 2.5 (hash-get distr :q1))


third-quartile Type: Function
stats::third-quartile Usage: (third-quartile number+)

Returns third quartile of distribution of provided arguments.

Example:
(ns-import 'stats)
(test::assert-error-msg (third-quartile) "expected at least one number")
(test::assert-equal 8 (third-quartile 10 4 8 7 6 5 9 3 2 1))


String forms

char->int Type: Function
root::char->int Usage: (char->int a-char)

Reads a char or string, which may be composed of one or more unicode scalar values, (see (doc ‘codepoints) for more information) and returns a sum of the values. This is not a hashing function, and only accepts one grapheme in the form of a string or character. Graphemes composed of the same unicode scalar values will result in the same integer value.’

Example:
(test::assert-error-msg (char->int (make-vec)) "char->int expects one argument of type Char or String")
(test::assert-error-msg (char->int) "char->int: Missing required argument, see (doc 'char->int) for usage.")
(test::assert-error-msg (char->int "a" "b") "char->int: Too many arguments, see (doc 'char->int) for usage.")
(test::assert-error-msg (char->int "ab") "char->int takes one grapheme, multiple were provided.")
(test::assert-error-msg (char->int "λ⚙") "char->int takes one grapheme, multiple were provided.")
(test::assert-equal 97 (char->int "a"))
(test::assert-equal 97 (char->int #\a))
(test::assert-equal 7101 (char->int #\स्))
(test::assert-equal 9881 (char->int (str "\" "u{2699}")))


codepoints Type: Function
root::codepoints Usage: (codepoints string)

Returns array of unicode scalars for each char in string. Note, a char is not a grapheme. The hindi word namaste (“न” “म” “स्” “ते”) written in Devanagari script is 4 graphemes, but 6 unicode scalar values, (“u{928}” “u{92e}” “u{938}” “u{94d}” “u{924}” “u{947}”); reference.

Example:
(test::assert-error-msg (codepoints) "codepoints: Missing required argument, see (doc 'codepoints) for usage.")
(test::assert-error-msg (codepoints (make-vec)) "codepoints expects one argument of type Char or String")
(test::assert-error-msg (codepoints "a" "b") "codepoints: Too many arguments, see (doc 'codepoints) for usage.")
(test::assert-equal (vec (str "\" "u{2699}")) (codepoints "⚙"))
(test::assert-equal (vec (str "\" "u{938}") ((str "\" "u{94d}"))) (codepoints "स्"))
(test::assert-equal (vec (str "\" "u{938}") ((str "\" "u{94d}"))) (codepoints #\स्))
(test::assert-equal (vec (str "\" "u{61}")) (codepoints "a"))
(test::assert-equal (vec (str "\" "u{61}")) (codepoints #\a))


do-unstr Type: SpecialForm
root::do-unstr Usage: (do-unstr arg0 ... argN) -> argN

Like do except if in an ‘str’ form then any processes will send their output to stdout instead of being captured as a string (‘undoes’ a str for processes). Note: does not convert arguments into strings, works like do.

Example:
; out> uses do-unstr so use a simplified one for these tests.
(defmacro tst-out> (file body) `(dyn *stdout* (open ,file :create :truncate) ,body))
(test::assert-equal "string 50 test
" (str "string" " " 50 " " (syscall 'echo "test")))
(test::assert-equal "string 50 test2
" (str "string" " " 50 " " (tst-out> "/tmp/test-str-echo" (syscall 'echo "test2"))))
(test::assert-equal "string 50 " (str "string" " " 50 " " (do-unstr (tst-out> "/tmp/test-str-echo" (syscall 'echo "test"))))


str Type: Function
root::str Usage: (str arg0 ... argN) -> string

Make a new string with it’s arguments. Arguments will be turned into strings. If an argument is a process then the output of the process will be captured and put into the string.

Example:
(test::assert-equal "stringsome" (str "string" "some"))
(test::assert-equal "string" (str "string" ""))
(test::assert-equal "string 50" (str "string" " " 50))
(test::assert-equal "string 50 test
" (str "string" " " 50 " " (syscall 'echo "test")))


str-append Type: Function
root::str-append Usage: (str-append string string) -> string

Make a new string by appending two strings.

Example:
(test::assert-equal "stringsome" (str-append "string" "some"))
(test::assert-equal "string" (str-append "string" ""))
(test::assert-equal "string " (str-append "string" " "))


str-bytes Type: Function
root::str-bytes Usage: (str-bytes string) -> int

Return number of bytes in a string (may be more then length). Strings are utf8 so it chars and bytes may not be a one to one match.

Example:
(test::assert-equal 4 (str-bytes "Stau"))
(test::assert-equal 0 (str-bytes ""))
; Note 5 chars and 6 bytes because of the final char.
(test::assert-equal 6 (str-bytes "StauΣ"))


str-cat-list Type: Function
root::str-cat-list Usage: (str-cat-list join-pattern sequence) -> string

Build a string by concatting a sequence with a join string.

Example:
(test::assert-equal "stringxxxyyyxxxsome" (str-cat-list "xxx" '("string" "yyy" "some")))
(test::assert-equal "string yyy some" (str-cat-list " " '("string" "yyy" "some")))
(test::assert-equal "stringyyysome" (str-cat-list "" '("string" "yyy" "some")))


str-clear! Type: Function
root::str-clear! Usage: (str-clear! string) -> string

Clears a string. This is a destructive form. Returns the string it was given.

Example:
(test::assert-equal "" (str-clear! (str "string")))
(def test-str-clear (str "def-string"))
(test::assert-equal "" (str-clear! test-str-clear))
(test::assert-equal "" test-str-clear)


str-contains Type: Function
root::str-contains Usage: (str-contains pattern string) -> t/nil

True if string contains pattern (both strings).

Example:
(test::assert-true (str-contains "Stau" "Stausomething"))
(test::assert-false (str-contains "StaU" "Stausomething"))
(test::assert-true (str-contains "some" "Stausomething"))
(test::assert-false (str-contains "Some" "Stausomething"))
(test::assert-true (str-contains "thing" "Stausomething"))
(test::assert-false (str-contains "Thing" "Stausomething"))
(test::assert-true (str-contains "someΣ" "StausomeΣthing"))


str-empty? Type: Function
root::str-empty? Usage: (str-empty? string) -> t/nil

Is a string empty? Let’s find out…

Example:
(test::assert-true (str-empty? ""))
(test::assert-true (str-empty? (str-trim " ")))
(test::assert-false (str-empty? " "))
(test::assert-false (str-empty? "string"))


str-iter-empty? Type: Function
root::str-iter-empty? Usage: (str-iter-empty? string) -> t/nil

Returns true if the iterator for the string is empty or finished.

Example:
(def test-iter-start "test")
(test::assert-true (str-iter-empty? test-iter-start))
(str-iter-start test-iter-start)
(test::assert-false (str-iter-empty? test-iter-start))
(test::assert-equal #\t (str-iter-next! test-iter-start))
(test::assert-equal #\e (str-iter-next! test-iter-start))
(test::assert-equal #\s (str-iter-next! test-iter-start))
(test::assert-equal #\t (str-iter-next! test-iter-start))
(test::assert-true (str-iter-empty? test-iter-start))
(def test-iter-start "test")
(test::assert-true (str-iter-empty? test-iter-start))
(str-iter-start test-iter-start)
(test::assert-false (str-iter-empty? test-iter-start))
(test::assert-equal #\t (str-iter-next! test-iter-start))
(test::assert-equal #\e (str-iter-next! test-iter-start))
(str-push! test-iter-start "one")
(test::assert-true (str-iter-empty? test-iter-start))
(str-iter-start test-iter-start)
(test::assert-false (str-iter-empty? test-iter-start))
(str-clear! test-iter-start)
(test::assert-true (str-iter-empty? test-iter-start))


str-iter-next! Type: Function
root::str-iter-next! Usage: (str-iter-next! string) -> char

Returns the next char in the iterator for string. Returns nil if iteration is done.

Example:
(def test-iter-start "y̆ΛλΣσ")
(str-iter-start test-iter-start)
(test::assert-false (str-iter-empty? test-iter-start))
(def test-iter-one (str-iter-next! test-iter-start))
(test::assert-equal #\y̆ test-iter-one)
(test::assert-true (= #\y̆ test-iter-one))
(test::assert-false (= #\y test-iter-one))
(test::assert-equal #\Λ (str-iter-next! test-iter-start))
(test::assert-equal #\λ (str-iter-next! test-iter-start))
(test::assert-equal #\Σ (str-iter-next! test-iter-start))
(test::assert-equal #\σ (str-iter-next! test-iter-start))
(test::assert-true (str-iter-empty? test-iter-start))


str-iter-peek Type: Function
root::str-iter-peek Usage: (str-iter-peek string) -> char

Returns the char that next will return in the iterator for string. Returns nil if iteration is done. Does not advance the iterator.

Example:
(def test-iter-start "y̆ΛλΣσ")
(str-iter-start test-iter-start)
(test::assert-false (str-iter-empty? test-iter-start))
(def test-iter-one (str-iter-next! test-iter-start))
(test::assert-equal #\y̆ test-iter-one)
(test::assert-true (= #\y̆ test-iter-one))
(test::assert-false (= #\y test-iter-one))
(test::assert-equal #\Λ (str-iter-peek test-iter-start))
(test::assert-equal #\Λ (str-iter-next! test-iter-start))
(test::assert-equal #\λ (str-iter-peek test-iter-start))
(test::assert-equal #\λ (str-iter-next! test-iter-start))
(test::assert-equal #\Σ (str-iter-peek test-iter-start))
(test::assert-equal #\Σ (str-iter-next! test-iter-start))
(test::assert-equal #\σ (str-iter-peek test-iter-start))
(test::assert-equal #\σ (str-iter-next! test-iter-start))
(test::assert-true (str-iter-empty? test-iter-start))


str-iter-start Type: Function
root::str-iter-start Usage: (str-iter-start string) -> string

Starts or resets the iterator over a string. Returns the input string with it’s iteration start created and at the first position. Using the str-iter-* functions is the proper way to get the chars of a string (since they are UTF a char is not a fixed size so direct indexing is very inefficient).

Example:
(def test-iter-start "test")
(test::assert-true (str-iter-empty? test-iter-start))
(str-iter-start test-iter-start)
(test::assert-false (str-iter-empty? test-iter-start))
(test::assert-equal #\t (str-iter-next! test-iter-start))
(test::assert-equal #\e (str-iter-next! test-iter-start))
(test::assert-equal #\s (str-iter-next! test-iter-start))
(test::assert-equal #\t (str-iter-next! test-iter-start))
(test::assert-true (str-iter-empty? test-iter-start))
(str-iter-start test-iter-start)
(test::assert-false (str-iter-empty? test-iter-start))
(test::assert-equal #\t (str-iter-next! test-iter-start))
(test::assert-equal #\e (str-iter-next! test-iter-start))
(str-iter-start test-iter-start)
(test::assert-false (str-iter-empty? test-iter-start))
(test::assert-equal #\t (str-iter-next! test-iter-start))
(test::assert-equal #\e (str-iter-next! test-iter-start))
(test::assert-equal #\s (str-iter-next! test-iter-start))
(test::assert-equal #\t (str-iter-next! test-iter-start))
(test::assert-true (str-iter-empty? test-iter-start))


str-lower Type: Function
root::str-lower Usage: (str-lower string) -> string

Get all lower case string from a string.

Example:
(test::assert-equal "stau" (str-lower "STAU"))
(test::assert-equal "stau" (str-lower "stau"))
(test::assert-equal "stau" (str-lower "Stau"))
(test::assert-equal "stau" (str-lower "StaU"))
(test::assert-equal "stau" (str-lower "sTaU"))


str-ltrim Type: Function
root::str-ltrim Usage: (str-ltrim string) -> string

Trim left whitespace from string.

Example:
(test::assert-equal "some string" (str-ltrim " some string"))
(test::assert-equal "some string " (str-ltrim " some string "))
(test::assert-equal "some string " (str-ltrim (str " some string ")))
(test::assert-equal "some string " (str-ltrim "some string "))
(test::assert-equal "some string" (str-ltrim "some string"))


str-map Type: Function
root::str-map Usage: (str-map lambda string) -> string

Make a new string by applying lambda to each char.

Example:
(test::assert-equal "XstringXstrX" (str-map (fn (ch) (if (= #\x ch) #\X ch)) "xstringxstrx"))
(def test-str-map (str-map (fn (ch) (if (= #\x ch) #\X ch)) "xstringxstrx"))
(test::assert-equal "XstringXstrX" test-str-map)
(test::assert-true (string? test-str-map))
(def test-str-map (str-map (fn (ch) (if (= #\x ch) #\X ch)) (str "xstringxstrx")))
(test::assert-equal "XstringXstrX" test-str-map)
(test::assert-true (string? test-str-map))


str-nth Type: Function
root::str-nth Usage: (str-nth n string) -> char

Get the nth char of a string.

Example:
(test::assert-equal #\a (str-nth 2 "stau"))
(test::assert-equal #\s (str-nth 0 "stau"))
(test::assert-equal #\u (str-nth 3 "stau"))


str-push! Type: Function
root::str-push! Usage: (str-push! string arg0 ... argN) -> string

Push the args (as strings) onto the string. This is a destructive form. Arguments will be turned into strings. Returns the string it was given.

Example:
(test::assert-equal "stringsome" (str-push! (str "string") "some"))
(def test-str-push (str "def-string"))
(test::assert-equal "def-stringsome" (str-push! test-str-push "some"))
(test::assert-equal "def-stringsome" test-str-push)


str-replace Type: Function
root::str-replace Usage: (str-replace string old-pattern new-pattern) -> string

Replace occurances of second string with third in the first string.

Example:
(test::assert-equal "some yyy string" (str-replace "some xxx string" "xxx" "yyy"))
(test::assert-equal "some yyy string yyy" (str-replace "some xxx string xxx" "xxx" "yyy"))
(test::assert-equal "yyy some yyy string yyy" (str-replace "xxx some xxx string xxx" "xxx" "yyy"))


str-rsplit Type: Function
root::str-rsplit Usage: (str-rsplit split-pattern string) -> vector

Use a pattern to split a string into reverse order.

Example:
(test::assert-equal '("some" "yyy" "string") (str-rsplit "xxx" "stringxxxyyyxxxsome"))
(test::assert-equal '("" "some" "yyy" "string") (str-rsplit "xxx" "stringxxxyyyxxxsomexxx"))
(test::assert-equal '("some" "yyy" "string") (str-rsplit " " "string yyy some"))
(test::assert-equal '("somexxxyyyxxxstring") (str-rsplit :whitespace "somexxxyyyxxxstring"))
(test::assert-equal '("somexxxyyyxxxstring") (str-rsplit "zzz" "somexxxyyyxxxstring"))


str-rsplitn Type: Function
root::str-rsplitn Usage: (str-rsplitn n split-pattern string) -> vector

Use a pattern to split a string with at most n items returned in reverse order.

Example:
(test::assert-equal '("some" "yyy" "string") (str-rsplitn 3 "xxx" "stringxxxyyyxxxsome"))
(test::assert-equal '("some" "yyy" "string") (str-rsplitn 4 "xxx" "stringxxxyyyxxxsome"))
(test::assert-equal '("other" "string" "somexxxyyy") (str-rsplitn 3 "xxx" "somexxxyyyxxxstringxxxother"))
(test::assert-equal '("somexxxyyyxxxstringxxxother") (str-rsplitn 1 "xxx" "somexxxyyyxxxstringxxxother"))
(test::assert-equal '() (str-rsplitn 0 "xxx" "somexxxyyyxxxstringxxxzero"))


str-rtrim Type: Function
root::str-rtrim Usage: (str-rtrim string) -> string

Trim right whitespace from string.

Example:
(test::assert-equal " some string" (str-rtrim " some string"))
(test::assert-equal " some string" (str-rtrim " some string "))
(test::assert-equal " some string" (str-rtrim (str " some string ")))
(test::assert-equal "some string" (str-rtrim "some string "))
(test::assert-equal "some string" (str-rtrim "some string"))


str-split Type: Function
root::str-split Usage: (str-split split-pattern string) -> vector

Use a pattern to split a string (:whitespace to split on whitespace).

Example:
(test::assert-equal '("some" "yyy" "string") (str-split "xxx" "somexxxyyyxxxstring"))
(test::assert-equal '("some" "yyy" "string" "") (str-split "xxx" "somexxxyyyxxxstringxxx"))
(test::assert-equal '("" "some" "yyy" "string" "") (str-split "xxx" "xxxsomexxxyyyxxxstringxxx"))
(test::assert-equal '("some" "yyy" "string") (str-split :whitespace "some yyy string"))
(test::assert-equal '("somexxxyyyxxxstring") (str-split :whitespace "somexxxyyyxxxstring"))
(test::assert-equal '("somexxxyyyxxxstring") (str-split "zzz" "somexxxyyyxxxstring"))


str-splitn Type: Function
root::str-splitn Usage: (str-splitn n split-pattern string) -> vector

Use a pattern to split a string with at most n items.

Example:
(test::assert-equal '("some" "yyy" "string") (str-splitn 3 "xxx" "somexxxyyyxxxstring"))
(test::assert-equal '("some" "yyy" "string") (str-splitn 4 "xxx" "somexxxyyyxxxstring"))
(test::assert-equal '("some" "yyy" "stringxxxother") (str-splitn 3 "xxx" "somexxxyyyxxxstringxxxother"))
(test::assert-equal '("somexxxyyyxxxstringxxxother") (str-splitn 1 "xxx" "somexxxyyyxxxstringxxxother"))
(test::assert-equal '() (str-splitn 0 "xxx" "somexxxyyyxxxstringxxxzero"))


str-starts-with Type: Function
root::str-starts-with Usage: (str-starts-with pattern string) -> t/nil

True if string start with pattern (both strings).

Example:
(test::assert-true (str-starts-with "Stau" "Stausomething"))
(test::assert-false (str-starts-with "StaU" "Stausomething"))


str-sub Type: Function
root::str-sub Usage: (str-sub string start [length]) -> string

Return a substring from a string given start (0 based) and optional length. If length is 0 or not provided produces the rest of the string from start to string end.

Example:
(test::assert-equal "string" (str-sub "stringxxxyyyxxxsome" 0 6))
(test::assert-equal "some" (str-sub "stringxxxyyyxxxsome" 15 4))
(test::assert-equal "yyy" (str-sub "stringxxxyyyxxxsome" 9 3))
(test::assert-equal "some" (str-sub "stringxxxyyyxxxsome" 15))


str-trim Type: Function
root::str-trim Usage: (str-trim string) -> string

Trim right and left whitespace from string.

Example:
(test::assert-equal "some string" (str-trim " some string"))
(test::assert-equal "some string" (str-trim " some string "))
(test::assert-equal "some string" (str-trim (str " some string ")))
(test::assert-equal "some string" (str-trim "some string "))
(test::assert-equal "some string" (str-trim "some string"))


str-upper Type: Function
root::str-upper Usage: (str-upper string) -> string

Get all upper case string from a string.

Example:
(test::assert-equal "STAU" (str-upper "STAU"))
(test::assert-equal "STAU" (str-upper "stau"))
(test::assert-equal "STAU" (str-upper "Stau"))
(test::assert-equal "STAU" (str-upper "StaU"))
(test::assert-equal "STAU" (str-upper "sTaU"))


with-padding Type: Lambda
root::with-padding Usage: (with-padding target padding padding-char &rest padding-keyword)

Given a “target” string, a keyword specifying the type of padding, an integer length to pad to “padding”, and a character to use for padding “padding-char”, return a string with length equal to the specified padding length, only if the target string is less than the amount of padding specified. The resultant string defaults to right padding and is composed of the target string followed by “padding” number of “padding-char”. If left or center padding is desired pass one of the keywords :left or :center as the final argument to the function. For completeness, the keyword :right is also supported.

Example:
(test::assert-equal "test......" (with-padding "test" 10 "."))
(test::assert-equal "test......" (with-padding "test" 10 "." :right))
(test::assert-equal "......test" (with-padding "test" 10 "." :left))
(test::assert-equal "...test..." (with-padding "test" 10 "." :center))
(test::assert-equal "..tests..." (with-padding "tests" 10 "." :center))


Struct forms

defstruct Type: Macro
struct::defstruct Usage: (defstruct name &rest fields)

Define a structure. This produces a lambda with name that will create an instance. Each ‘field’ will add an attribute, method or trait. Use (attr-name doc-str? default? [:rw | :ro | :wo]?) if a final access modifier is not provided then it is private. NOTE: for attributes, if the default value is a string then doc-str is not optional (but can be empty). Use (:fn name doc-str? body) to add a method. Use (:impl trait) to add a trait.

Example:
(struct::defstruct test-struct
; fields
(a "a private attribute" nil)
(b "a read/write attribute" "bee" :rw)
(c "a read only attribute" "see" :ro)
(d "a write only attribute" "dee" :wo)
; methods
(:fn what-d (self) d)
(:fn what-a (self) a))
(def ts (test-struct))
(assert-equal nil (ts :what-a))
(assert-equal "dee" (ts :what-d))
(ts :set-d "something else")
(assert-equal "something else" (ts :what-d))
(assert-equal "bee" (ts :b))
(assert-equal "see" (ts :c))
(ts :set-b "queen")
(assert-equal "queen" (ts :b))


deftrait Type: Macro
struct::deftrait Usage: (deftrait name &rest fields)

Define a trait. Traits define methods that are added to structures (and usually require one or more methods in the struct. Use them to provide common functionality shared by different structures. Use (:fn name doc-str? body) to add a method.

Example:
(ns-push 'test-deftrait)
(struct::deftrait test-trait
; Require what-a and what-d in the structures that implement this trait.
(:fn aaa (self) (self :what-a))
(:fn ddd (self) (self :what-d)))
(struct::defstruct test-struct
; fields
(a "a private attribute" nil)
(b "a read/write attribute" "bee" :rw)
(c "a read only attribute" "see" :ro)
(d "a write only attribute" "dee" :wo)
; methods
(:fn what-d (self) d)
(:fn what-a (self) a)
(:impl test-deftrait::test-trait))
(def ts (test-struct))
(test::assert-equal nil (ts :aaa))
(test::assert-equal "dee" (ts :ddd))
(ts :set-d "something else")
(test::assert-equal "something else" (ts :ddd))
(test::assert-equal "bee" (ts :b))
(test::assert-equal "see" (ts :c))
(ts :set-b "queen")
(test::assert-equal "queen" (ts :b))
(ns-pop)


System forms

bg Type: Function
root::bg Usage: (bg job-id?)

Put a job in the background. If no job id is specified use the last job.

Example:
;(bg)
#t


exit Type: Function
root::exit Usage: (exit code?)

Exit shell with optional status code.

Example:
; Exit is overridden in the test harness...
;(test::assert-equal 10 (wait (fork (exit 10))))
;(test::assert-equal 11 (wait (fork (exit 11))))
;(test::assert-equal 12 (wait (fork (exit 12))))
#t


export Type: Function
root::export Usage: (export symbol string) -> string

Export a key and value to the shell environment. Second arg will be made a string and returned. Key can not contain the ‘=’ character.

Example:
(test::assert-equal "ONE" (export 'TEST_EXPORT_ONE "ONE"))
(test::assert-equal "ONE" $TEST_EXPORT_ONE))
(test::assert-equal "ONE1" (export 'TEST_EXPORT_ONE ONE1))
(test::assert-equal "ONE1" $TEST_EXPORT_ONE))
(test::assert-equal "TWO" (export "TEST_EXPORT_TWO" "TWO"))
(test::assert-equal "TWO" $TEST_EXPORT_TWO))
(test::assert-equal "THREE" $(export TEST_EXPORT_THREE THREE))
(test::assert-equal "THREE" $TEST_EXPORT_THREE))
(test::assert-error (export '=TEST_EXPORT_THREE "THREE"))
(test::assert-error (export 'TEST=EXPORT_THREE "THREE"))
(test::assert-error (export 'TEST_EXPORT_THREE= "THREE"))
(test::assert-error $(export TEST_EXPORT_THREE= THREE))


fg Type: Function
root::fg Usage: (fg job-id?)

Put a job in the foreground. If no job id is specified use the last job.

Example:
;(fg)
#t


fork Type: SpecialForm
root::fork Usage: (fork exp) -> process

Forks the provided expression in the background as a job and returns the process object. If the expression that is forked returns an integer (that fits an i32) then it will become the exit code. Calling exit explicitly will also set the exit code. Otherwise exit code is 0 for success and 1 for an error.

Example:
(def fork-test (fork (+ (* 11 5) 2)))
(test::assert-equal 57 (wait fork-test))
(def fork-time (time (wait (fork (sleep 1000)))))
(test::assert-true (> fork-time 1.0))


get-env Type: SpecialForm
root::get-env Usage: (get_env key) -> string

Lookup key in the system environment (env variable). Returns an empty sting if key does not exist. Note: key is not evaluated.

Example:
(test::assert-equal "ONE" (export 'TEST_EXPORT_ONE "ONE"))
(test::assert-equal "ONE" $TEST_EXPORT_ONE))
(test::assert-equal "ONE" (get-env TEST_EXPORT_ONE))
(test::assert-equal "" (get-env TEST_EXPORT_ONE_NA))


get-pid Type: Function
root::get-pid Usage: (get-pid)

Return the pid of running process (shell).

Example:
(test::assert-true (int? (get-pid)))


jobs Type: Function
root::jobs Usage: (jobs)

Print list of jobs with ids.

Example:
;(jobs)
#t


pid Type: Function
root::pid Usage: (pid proc)

Return the pid of a process.

Example:
(def pid-test (syscall 'echo "-n"))
(test::assert-true (int? (pid pid-test)))
(test::assert-true (int? (pid (fork ((fn () nil))))))
(test::assert-error (pid 1))


pipe Type: Function
root::pipe Usage: (pipe [expression]+)

Setup a pipe between processes or expressions. Pipe will take one or more expressions, each one but the last will be forked into a new process with it’s stdin being the output of the last expression. The first expression uses the current stdin and the last expression outputs to the current stdout. Pipe works with system commands as well as sl-sh forms (lambdas, etc). Note it connects the stdin/stdout of processes so if used with a lambda it should read stdin to get the previous output and write to stdout to pass to the next expression in the pipe (i.e. pipe will not interact with parameters or anything else). If pipe starts with :err then stderr will also be piped into the output, ie (pipe :err (…)(…)…). Pipes also support using a read file as the first expression (the file contents become stdin for the next form) and a write file as the last expression (previous output will be written to the file). For instance pipe can be used to copy a file with (pipe (open IN_FILE :read)(open OUT_FILE :create)), note this example does not close the files. Pipes can be nested including piping through a lambda that itself uses pipes. Pipe will return a multiple values, the first/primary is the final form for the pipe and the process objects for each part of the pipe are next (first element can be found with (values-nth 1 return-val), etc).

Example:
(def pipe-test (str (pipe (print "one
two
three")(syscall 'grep "two"))))
(test::assert-equal "two
" pipe-test)
(def pipe-test (str (pipe (pipe (syscall 'echo "one
two
twotwo
three")(syscall 'grep "two"))(syscall 'grep "twotwo"))))
(test::assert-equal "twotwo
" pipe-test)
(def pipe-test-dir (str (temp-dir)"/tst-pipe-dir"))
$(mkdir $pipe-test-dir)
(def tsync (open "${pipe-test-dir}/test1" :create))
(pipe (print "one
two
two2
three") (syscall 'grep "two") tsync)
(close tsync)
(def topen (open "${pipe-test-dir}/test1" :read))
(test::assert-equal "two
" (read-line topen))
(test::assert-equal "two2
" (read-line topen))
(test::assert-false (read-line topen))
(close topen)
(def topen (open "${pipe-test-dir}/test1" :read))
(def pipe-test (str (pipe topen (syscall 'grep "two2"))))
(close topen)
(test::assert-equal "two2
" pipe-test)
$(rm "${pipe-test-dir}/test1")
(let ((file-name "${pipe-test-dir}/pipe-err.test")
(fin))
(err> (open "${pipe-test-dir}/pipe-test.junk" :create) (do
(pipe (eprintln "error")(do (print *stdin*)(println "normal"))(open file-name :create :truncate))
(set! fin (open file-name :read))
(test::assert-equal "normal\n" (read-line fin))
(test::assert-equal nil (read-line fin))
(close fin)
(pipe :err (eprintln "error")(do (print *stdin*)(println "normal"))(open file-name :create :truncate))
(set! fin (open file-name :read))
(test::assert-equal "error\n" (read-line fin))
(test::assert-equal "normal\n" (read-line fin))
(close fin)))
$(rm "${pipe-test-dir}/pipe-test.junk")
$(rm $file-name)
)
$(rmdir $pipe-test-dir)


reap-jobs Type: Function
root::reap-jobs Usage: (reap-jobs) -> nil

Reaps any completed jobs. Only intended to be used by code implemeting the REPL loop or something similiar, this is probably not the form you are searching for.

Example:
;(reap-jobs)
#t


sleep Type: Function
root::sleep Usage: (sleep milliseconds) -> nil

Sleep for the provided milliseconds (must be a positive integer).

Example:
(def test-sleep-var (time (sleep 1000)))
(assert-true (> test-sleep-var 1.0))


syscall Type: Function
root::syscall Usage: (syscall system-command arg0 ... argN)

Execute the provided system command with the supplied arguments. System-command can evalute to a string or symbol. The args (0..n) are evaluated.

Example:
(def test-syscall-one (str (syscall "echo" "-n" "syscall-test")))
(test::assert-equal "syscall-test" test-syscall-one)
(def test-syscall-one (str (syscall 'echo "-n" "syscall-test2")))
(test::assert-equal "syscall-test2" test-syscall-one)
(def test-syscall-echo "echo")
(def test-syscall-one (str (syscall test-syscall-echo "-n" "syscall-test3")))
(test::assert-equal "syscall-test3" test-syscall-one)


time Type: Function
root::time Usage: (time form) -> eval-time

Evalutes the provided form and returns the seconds it ran for (as float with fractional part).

Example:
(def test-sleep-var (time (sleep 1100)))
(assert-true (> test-sleep-var 1.1))


umask Type: Function
root::umask Usage: (umask [mask])

Takes 0 or 1 argument(s). If no arguments are provided the current file mode creation mask will be returned. The value returned is the new value of the mask as an octal string (which can be fed back into the umask form if needed). If an argument is provided that value will be interpreted as a mask, applied, and the new file mask creation mask will be returned. Specify mask as an integer in octal form, or a string in the form of a symbolic mode mask (see fig. a). When an integer is provided the value replaces the current value of the file creation mode mask. When a string is provided as a symbolic mode mask the current value of the system’s umask is used to generate the new mask according to the specifications of the provided permissions operator. By default most Linux distros will set it to 022 or 002. If provided mode begins with a digit, it is interpreted as an octal number; if not, it is interpreted as a symbolic mode mask. $> umask a+rw,go-x => 0011 ;;; all users can read and write, only user can execute. $> umask 027 => 0027 ;;; user can read, write and execute, group can read and write but not execute, and other has none. $> umask u-x => 0122 ;;; user can not execute, unspecified permissions are left unchanged from default, 0022. ;;; fig. a ;;; ;;; symbolic mode mask: ;;; - [user class symbol(s)][permissions operator][permission symbol(s)][,]… ;;; - valid user class symbols: ‘u’, ‘g’, ‘o’, ‘a’ ;;; - ‘u’: the owner user ;;; - ‘g’: the owner group ;;; - ‘o’: others (not ‘u’ or ‘g’) ;;; - ‘a’: all users ;;; - valid permissions operators: ‘+’, ‘-‘, ‘=’ ;;; - ‘+’: enables specified permissions for user classes and leaves unspecified permissions ;;; unchanged ;;; - ‘-‘: disables specified permissions for user classes and leaves unspecified permissions ;;; unchanged ;;; - ‘=’: allow the specified permisssions for the specified user classes, permissions for ;;; unspecified user class remain unchanged. ;;; - valid permission symbols: ‘r’, ‘w’, x’ ;;; - ‘r’ ;;; - file is viewble ;;; - directory’s contents can be viewed ;;; - ‘w’ ;;; - file can be created, edited, or deleted ;;; - directory allows file creation and deletion. ;;; - ‘x’ ;;; - file is executable ;;; - directory can be entered ‘cd’ or contents can be executed. ;;; - one of the user class symbols or valid permission symbols can be left blank to specify all ;;; symbols.

Example:
#t


unexport Type: Function
root::unexport Usage: (unexport symbol)

Remove a var from the current shell environment.

Example:
(test::assert-equal "ONE" (export 'TEST_EXPORT_ONE "ONE"))
(test::assert-equal "ONE" $TEST_EXPORT_ONE))
(unexport 'TEST_EXPORT_ONE)
(test::assert-equal "" $TEST_EXPORT_ONE))


wait Type: Function
root::wait Usage: (wait proc-to-wait-for)

Wait for a process to end and return it’s exit status. Wait can be called multiple times if it is given a process object (not just a numeric pid).

Example:
(def wait-test (wait (err>null (syscall 'ls "/does/not/exist/123"))))
(test::assert-true (> wait-test 0))
(def wait-test2 (fork (* 11 5)))
(test::assert-equal 55 (wait wait-test2))
(test::assert-equal 55 (wait wait-test2))
(test::assert-equal 55 (wait wait-test2))


Test forms

assert-equal Type: Lambda
test::assert-equal Usage: (assert-equal expected-val right-val &rest args)

Test expected-val and right-val for equality.

Example:
(test::assert-true (test::assert-equal 1 1))
(test::assert-false (test::assert-equal (list 1 2) (list 1)))
(test::assert-true (test:: assert-equal (list 1 2) (list 1 2)))


assert-error Type: Macro
test::assert-error Usage: (assert-error form)

Test asserts an error is thrown.

Example:
(test::assert-error (err "error thrown"))


assert-error-msg Type: Macro
test::assert-error-msg Usage: (assert-error-msg form msg)

Test asserts an error is thrown with a given message.

Example:
(test::assert-error-msg (err "error thrown") "error thrown")


assert-false Type: Lambda
test::assert-false Usage: (assert-false value &rest args)

Test for falsiness.

Example:
(test::assert-false #f)
(test::assert-false nil)


assert-not-equal Type: Lambda
test::assert-not-equal Usage: (assert-not-equal expected-val right-val &rest args)

Test expected-val and right-val are not equal.

Example:
(test::assert-false (test::assert-not-equal 1 1))
(test::assert-true (test::assert-not-equal 1 2))
(test::assert-false (test::assert-not-equal (list 1 2 3) (list 1 2 3))


assert-true Type: Lambda
test::assert-true Usage: (assert-true value &rest args)

Test for truthiness.

Example:
(test::assert-true #t)


run-example Type: Macro
test::run-example Usage: (run-example sym)

Given a symbol, run any tests found in example section if exists.

Threading-macros forms

-> Type: Macro
root::-> Usage: (-> &rest args)

inserts result of previous expression as second argument to current expression. First argument is not evaluated.

Example:
(assert-equal
(str "I go at the beginning.I'll be stuck in the middle.I'll be at the end.")
(-> "I go at the beginning."
(str "I'll be stuck in the middle.")
(str "I'll be at the end.")))


->> Type: Macro
root::->> Usage: (->> &rest args)

inserts result of previous expression as last argument to current expression. First argument is not evaluated.

Example:
(assert-equal
(str "I'll be at the beginning.I'll be more in the middle.I go at the end.")
(->> "I go at the end."
(str "I'll be more in the middle.")
(str "I'll be at the beginning.")))


chain Type: Macro
root::chain Usage: (chain init arg0 &rest args)

Inserts result of previous expression into place indicated by the _ symbol in the next expression. This macro is useful when nested actions need to occur but when a more sequential enumeration of steps is preferable. To demonstrate a sequence of operations: (fn (x) (delta (charlie (bravo (alpha x))))) can be unwound, and more idiomatically stated with the chain macro: (fn (x) (chain x (alpha _) (bravo _) (charlie _) (delta _))) The flexibility of using the _ symbol as a placeholder means subsequent results can be “threaded” into any desired place in a clause which is an advantage over the thread first, -> and thread last, , macros

Example:
(test::assert-equal "Ordered sentence: I will become a properly worded statement."
(chain "a properly worded "
(str "will " "become " _)
(str "I " _ "statement.")
(str "Ordered sentence: " _)))
(test::assert-equal 3 (chain 7 (% _ 4)))
(test::assert-equal 9 (chain 7 (% _ 4) (+ 1 8)))
(test::assert-equal (list 6 12 18) (collect (chain 7
(% _ 4)
(range _ 10)
(map (fn (x) (* x 2)) _)
(filter (fn (x) (= 0 (% x 3))) _))))


chain-and Type: Macro
root::chain-and Usage: (chain-and init arg0 &rest args)

Evaluates each sexp, if true, inserts result of previous expression into place indicated by the _ symbol. This macro is useful when nested actions need to take place but the operations should stop and return nil if any step evaluates to false.

Example:
(test::assert-false (chain-and "howdy" (string? _) (= _ "howdy")))
(test::assert-true (chain-and "howdy" (str _ " partner") (= _ "howdy partner")))
(defn formatted? (alleged-time-str)
(let* ((do-fst (fn (tst start end)
(fn (orig-string)
(let ((result (get-error
(chain orig-string
(str-sub _ start (- end start))
(str->int _)
(tst _)))))
(if (= :ok (car result))
(if (cdr result) orig-string nil)
nil)))))
(valid-year? (do-fst (fn (x) (> x -1)) 0 4))
(valid-month? (do-fst (fn (x) (and (> x 0) (< x 13))) 4 6))
(valid-day? (do-fst (fn (x) (and (> x 0) (< x 32))) 6 8))
(valid-hour? (do-fst (fn (x) (and (> x 0) (< x 24))) 9 11))
(valid-minute? (do-fst (fn (x) (and (> x -1) (< x 60))) 11 13))
(valid-second? (do-fst (fn (x) (and (> x -1) (< x 60))) 13 15))
(is-zulu? (fn (orig-string) (= "Z" (str-sub orig-string 15 1)))))
(chain-and alleged-time-str
(valid-year? _)
(valid-month? _)
(valid-day? _)
(valid-hour? _)
(valid-minute? _)
(valid-second? _)
(is-zulu? _)
#t)))
(test::assert-true (formatted? "20210227T154705Z"))
(test::assert-false (formatted? "20210227T154705P"))
(test::assert-false (formatted? "2021022TT154705Z"))
(test::assert-false (formatted? "20210237T154705Z"))
(test::assert-false (formatted? "2021222TT154705Z"))
(test::assert-false (formatted? "20210227T254705Z"))
(test::assert-false (formatted? "20210227T158705Z"))
(test::assert-false (formatted? "20210227T154795Z"))


chain-when Type: Macro
root::chain-when Usage: (chain-when init arg0 &rest args)

Tests the car of each arg0/args pair. If true the cdr of the arg0/args pair is evaluated. The chaining component of this macro works by threading init through the cdr of each pair whose car evaluates to true. Useful for building or modifying an object based on a set of boolean conditions.

Example:
(defn add-number-attributes (n)
(chain-when (make-hash)
((not (= (% n 2) 0)) (hash-set! _ :property :odd))
((= (% n 2) 0) (hash-set! _ :property :even))
((= 0 n) (hash-set! _ :zero :zero))
((= 42 n) (err "N CAN NOT BE 42"))
((> n 0) (hash-set! _ :symmetry :positive))
((< n 0) (hash-set! _ :symmetry :negative))))
(test::assert-equal :odd (hash-get (add-number-attributes 3) :property))
(test::assert-equal :even (hash-get (add-number-attributes 4) :property))
(test::assert-false (hash-get (add-number-attributes 4) :zero))
(test::assert-equal :positive (hash-get (add-number-attributes 4) :symmetry))
(test::assert-equal :negative (hash-get (add-number-attributes -4) :symmetry))
(test::assert-equal :zero (hash-get (add-number-attributes 0) :zero))
(test::assert-error-msg (add-number-attributes 42) "N CAN NOT BE 42")


Type forms

These forms provide information/tests about an objects underlying type.

boolean? Type: Function
root::boolean? Usage: (boolean? expression)

True if the expression is true(#t) or false(#f), false otherwise.

Example:
(test::assert-true (boolean? #f))
(test::assert-true (boolean? #t))
(test::assert-false (boolean? nil))
(test::assert-false (boolean? nil))
(test::assert-false (boolean? 1))
(test::assert-false (boolean? "str"))


builtin? Type: Function
root::builtin? Usage: (builtin? expression)

True if the expression is a builtin function or special form, false otherwise.

Example:
(test::assert-true (builtin? type))
(test::assert-true (builtin? if))
(test::assert-false (builtin? (fn () ())))
(test::assert-false (builtin? caar))
(test::assert-false (builtin? 1))


char? Type: Function
root::char? Usage: (char? expression)

True if the expression is a char, false otherwise.

Example:
(test::assert-true (char? #\a))
(test::assert-false (char? 1))
(test::assert-false (char? "a"))


false? Type: Function
root::false? Usage: (false? expression)

True if the expression is false(#f) (false type NOT nil), false otherwise.

Example:
(test::assert-true (false? #f))
(test::assert-false (false? nil))
(test::assert-false (false? nil))
(test::assert-false (false? 1))
(test::assert-false (false? "str"))


falsey? Type: Function
root::falsey? Usage: (falsey? under-test) -> bool

Returns true if the expression under-test evaluates to nil or false.

Example:
(test::assert-true (falsey? nil))
(test::assert-true (falsey? #f))
(test::assert-false (falsey? #t))
(test::assert-false (falsey? "false"))


file? Type: Function
root::file? "Usage: (file? expression)

True if the expression is a file, false otherwise.

Example:
(test::assert-true (file? (open :stdout)))
(test::assert-false (file? (fn () ())))
(test::assert-false (file? caar))
(test::assert-false (file? 1))


float->int Type: Function
root::float->int Usage: (float->int float) -> int

Cast a float as an int. Narrows the float if necessary to the max allowable int. If float is NaN 0 is returned.

Example:
(test::assert-equal 0 (float->int 0.0))
(test::assert-equal 10 (float->int 10.0))
(test::assert-equal 10 (float->int 10.1))
(test::assert-equal 10 (float->int 10.5))
(test::assert-equal 10 (float->int 10.9))
(test::assert-equal -101 (float->int -101.99))
(test::assert-error (float->int "not int"))


float? Type: Function
root::float? Usage: (float? expression)

True if the expression is a float, false otherwise.

Example:
(test::assert-true (float? 1.5))
(test::assert-false (float? 1))


func? Type: Macro
root::func? Usage: (func? to-test)

True if the expression is a builtin?, a lambda?, or a macro?

Example:
(def func?-test 1)
(test::assert-false (func? func?-test))
(test::assert-true (func? car))
(test::assert-true (func? first))
(test::assert-true (func? let))


hash? Type: Function
root::hash? Usage: (hash? expression)

True if the expression is a hash map, false otherwise.

Example:
(test::assert-true (hash? (make-hash)) "make-vec")
(test::assert-false (hash? 1))
(test::assert-false (hash? '(1 2 3)))
(test::assert-false (hash? (list)))
(test::assert-false (hash? (vec)))


int->float Type: Function
root::int->float Usage: (int->float int) -> float

Cast an int as a float.

Example:
(test::assert-equal 0 (int->float 0))
(int->float 10))
(test::assert-equal -101 (int->float -101))
(test::assert-error (int->float "not int"))


int? Type: Function
root::int? Usage: (int? expression)

True if the expression is an int, false otherwise.

Example:
(test::assert-true (int? 1))
(test::assert-false (int? 1.5))


lambda? Type: Function
root::lambda? Usage: (lambda? expression)

True if the expression is a lambda, false otherwise.

Example:
(test::assert-true (lambda? (fn () ())))
(test::assert-true (lambda? caar))
(test::assert-false (lambda? 1))
(test::assert-false (lambda? if))


list? Type: Function
root::list? Usage: (list? expression)

True if the expression is a list, false otherwise.

Example:
(test::assert-true (list? '(1 2 3)) "reader macro")
(test::assert-true (list? (list 1 2 3)) "list")
(test::assert-false (list? 1))
(test::assert-false (list? '#(1 2 3)))
(test::assert-false (list? (vec)))
(test::assert-false (list? '(1 . 2)))


macro? Type: Function
root::macro? Usage: (macro? expression)

True if the expression is a macro, false otherwise.

Example:
(test::assert-true (macro? (macro () ())))
(test::assert-true (macro? defn))
(test::assert-false (macro? 1))
(test::assert-false (macro? if))


nil? Type: Function
root::nil? Usage: (nil? expression)

True if the expression is nil, false otherwise.

Example:
(test::assert-true (nil? nil))
(test::assert-false (nil? #t))


none? Type: Function
root::none? Usage: (none? expression)

True if the expression is nil (aka none/nothing), false otherwise.

Example:
(test::assert-true (none? nil))
(test::assert-true (none? '()))
(test::assert-false (none? #t))
(test::assert-false (none? '(1)))


pair? Type: Function
root::pair? Usage: (pair? expression)

True if the expression is a pair, false otherwise.

Example:
(test::assert-true (pair? '(1 . 2)) "reader macro")
(test::assert-true (pair? (join 1 2)) "join")
(test::assert-true (pair? '(1 2)))
(test::assert-false (pair? 1))
(test::assert-false (pair? '#(1 2 3)))
(test::assert-false (pair? (vec)))


process? Type: Function
root::process? Usage: (process? expression)

True if the expression is a process, false otherwise.

Example:
(test::assert-true (process? (syscall 'true)))
(test::assert-true (process? (fork ((fn () nil)))))
(test::assert-false (process? (fn () ())))
(test::assert-false (process? caar))
(test::assert-false (process? 1))


regex? Type: Function
root::regex? Usage: (regex? expression)

True if the expression is a regex, false otherwise.

Example:
(test::assert-true (regex? (make-regex "\d{2}-\d{2}-\d{4}")))
(test::assert-true (regex? #/[a-z]+/))
(test::assert-false (regex? 1.5))


some? Type: Function
root::some? Usage: (some? expression)

True if the expression is NOT nil (aka something), false otherwise. Note that anything other then nil (including false) is something.

Example:
(test::assert-false (some? nil))
(test::assert-false (some? '()))
(test::assert-true (some? #t))
(test::assert-true (some? '(1)))


str->float Type: Function
root::str->float Usage: (str->float string) -> float

If string is a valid representation of a float return that float. Error if not.

Example:
(test::assert-equal 0 (str->float "0"))
(test::assert-equal 10.0 (str->float "10.0"))
(test::assert-equal 10.5 (str->float "10.5"))
(test::assert-equal 101 (str->float "101"))
(test::assert-equal -101.95 (str->float "-101.95"))
(test::assert-error (str->float "not int"))
(test::assert-error (str->float "--10"))


str->int Type: Function
root::str->int Usage: (str->int string) -> int

If string is a valid representation of an integer return that int. Error if not.

Example:
(test::assert-equal 0 (str->int "0"))
(test::assert-equal 101 (str->int "101"))
(test::assert-equal -101 (str->int "-101"))
(test::assert-error (str->int "not int"))
(test::assert-error (str->int "10.0"))
(test::assert-error (str->int "--10"))


string? Type: Function
root::string? Usage: (string? expression)

True if the expression is a string, false otherwise.

Example:
(test::assert-true (string? "string"))
(test::assert-false (string? 1))


sym Type: Function
root::sym Usage: (sym expression+) -> symbol

Takes one or more forms, converts them to strings, concatenates them and returns a symbol with that name.

Example:
(def test-to-symbol-sym nil)
(test::assert-true (symbol? (sym 55)))
(test::assert-true (symbol? (sym 55.0)))
(test::assert-true (symbol? (sym "to-symbol-test-new-symbol")))
(test::assert-true (symbol? (sym (str "to-symbol-test-new-symbol-buf"))))
(test::assert-true (symbol? (sym 'test-to-symbol-sym)))
(set! test-to-symbol-sym "testing-sym")
(test::assert-equal "testing-sym" (sym->str (sym test-to-symbol-sym)))
(test::assert-true (symbol? (sym (sym->str 'test-to-symbol-sym))))


sym->str Type: Function
root::sym->str Usage: (sym->str symbol) -> string

Convert a symbol to the string representation representation of it’s name. The string will be the symbol name as a string.

Example:
(def test-sym->str-sym nil)
(test::assert-true (string? (sym->str 'test-sym->str-sym)))
(test::assert-equal "test-sym->str-sym" (sym->str 'test-sym->str-sym))


symbol? Type: Function
root::symbol? Usage: (symbol? expression)

True if the expression is a symbol, false otherwise.

Example:
(test::assert-true (symbol? 'symbol))
(test::assert-false (symbol? 1))


true? Type: Function
root::true? Usage: (true? expression)

True if the expression is true(#t) (true type NOT non-nil), false otherwise.

Example:
(test::assert-true (true? #t))
(test::assert-false (true? #f))
(test::assert-false (true? nil))
(test::assert-false (true? 1))
(test::assert-false (true? "str"))


type Type: Function
root::type Usage: (type expression)

Return the type of the given expression as a string. Types are: True False Float Int Symbol String Char Lambda Macro Process SpecialForm Function Vector Pair Nil HashMap File

Example:
(test::assert-equal "True" (type #t))
(test::assert-equal "False" (type #f))
(test::assert-equal "Float" (type 1.1))
(test::assert-equal "Int" (type 1))
(test::assert-equal "Symbol" (type 'symbol))
(def type-sym 'symbol)
(test::assert-equal "Symbol" (type type-sym))
(test::assert-equal "String" (type "string"))
(test::assert-equal "Char" (type #\a))
(test::assert-equal "Lambda" (type (fn () ())))
(test::assert-equal "Macro" (type (macro () ())))
(test::assert-equal "Process" (type (syscall 'true)))
(test::assert-equal "SpecialForm" (type if))
(test::assert-equal "Function" (type type))
(test::assert-equal "Vector" (type '#(1 2 3)))
(def type-vec '#(4 5 6))
(test::assert-equal "Vector" (type type-vec))
(test::assert-equal "Pair" (type '(1 . 2)))
(test::assert-equal "Pair" (type '(1 2 3)))
(test::assert-equal "Nil" (type nil))
(test::assert-equal "Nil" (type '()))
(test::assert-equal "HashMap" (type (make-hash)))
(test::assert-equal "File" (type (open :stdin)))


values? Type: Function
root::values? Usage: (values? expression)

True if the expression is multi values object, false otherwise. NOTE: A values object will ALSO be the type of its first value.

Example:
(test::assert-true (values? (values 1 "str" 5.5)))
(test::assert-false (values? '(1 2 3)))
(test::assert-false (values? '(1 . 3)))
(test::assert-false (values? 1))
(test::assert-true (int? (values 1 "str" 5.5)))
(test::assert-false (string? (values 1 "str" 5.5)))
(test::assert-false (float? (values 1 "str" 5.5)))
(def test-is-values (values 1 2 3 "string" 1.5))
(test::assert-true (values? test-is-values))
(test::assert-true (int? test-is-values))
(test::assert-false (string? test-is-values))
(test::assert-false (float? test-is-values))


vec? Type: Function
root::vec? Usage: (vec? expression)

True if the expression is a vector, false otherwise.

Example:
(test::assert-true (vec? '#(1 2 3)) "reader macro")
(test::assert-true (vec? (make-vec)) "make-vec")
(test::assert-true (vec? (vec 1 2 3)) "vec")
(test::assert-false (vec? 1))
(test::assert-false (vec? '(1 2 3)))
(test::assert-false (vec? (list)))


Vector forms

Forms ending in ‘!’ are destructive and change the underlying vector, other forms do not make changes to the the provided vector. They are usable in place of a list for purposes of lambda calls, parameters, etc (they work the same as a list made from pairs but are vectors not linked lists). Use #() to declare them in code (i.e. ‘#(1 2 3) or #(+ 1 2)).

make-vec Type: Function
root::make-vec Usage: (make-vec capacity default)

Make a new vector with capacity and default item(s).

Example:
(test::assert-equal '() (make-vec))
(test::assert-equal '(x x x) (make-vec 3 'x))
(test::assert-equal '(nil nil nil nil nil) (make-vec 5 nil))
(test::assert-equal '() (make-vec 5))


vec Type: Function
root::vec Usage: (vec item1 item2 .. itemN)

Make a new vector with items.

Example:
(test::assert-equal '() (vec))
(test::assert-equal '(1 2 3) (vec 1 2 3))


vec-clear! Type: Function
root::vec-clear! Usage: (vec-clear! vector)

Clears a vector. This is destructive!

Example:
(def test-clear-vec (vec 1 2 3))
(test::assert-false (vec-empty? test-clear-vec))
(vec-clear! test-clear-vec)
(test::assert-true (vec-empty? test-clear-vec))


vec-empty? Type: Function
root::vec-empty? Usage: (vec-empty? vector)

True if the vector is empty.

Example:
(test::assert-true (vec-empty? '#()))
(test::assert-false (vec-empty? '#(1 2 3)))


vec-insert! Type: Function
root::vec-insert! Usage: (vec-insert! vector index new-element) -> vector

Inserts new-element at index and moves following elements right in vector. This is destructive!

Example:
(def test-insert-nth-vec (vec 1 2 3))
(test::assert-equal '(1 2 3) test-insert-nth-vec)
(vec-insert! test-insert-nth-vec 1 5)
(test::assert-equal '(1 5 2 3) test-insert-nth-vec)
(vec-insert! test-insert-nth-vec 2 6)
(test::assert-equal '(1 5 6 2 3) test-insert-nth-vec)
(vec-insert! test-insert-nth-vec 0 4)
(test::assert-equal '(4 1 5 6 2 3) test-insert-nth-vec)


vec-nth Type: Function
root::vec-nth Usage: (vec-nth vector index) -> object

Get the nth element (0 based) of a vector. If you need the equivalent operation on a list use nth.

Example:
(test::assert-equal 5 (vec-nth '#(1 2 3 4 5 6) 4))
(test::assert-equal 1 (vec-nth '#(1 2 3 4 5 6) 0))
(test::assert-equal 3 (vec-nth '#(1 2 3 4 5 6) 2))
(test::assert-equal 6 (vec-nth '#(1 2 3 4 5 6) 5))


vec-pop! Type: Function
root::vec-pop! Usage: (vec-pop! vector) -> object

Pops the last object off of the end of the vector. This is destructive!

Example:
(def test-pop-vec (vec 1 2 3))
(test::assert-equal 3 (vec-pop! test-pop-vec))
(test::assert-equal '(1 2) test-pop-vec)
(test::assert-equal 2 (vec-pop! test-pop-vec))
(test::assert-equal '(1) test-pop-vec)
(test::assert-equal 1 (vec-pop! test-pop-vec))
(test::assert-equal '() test-pop-vec)


vec-push! Type: Function
root::vec-push! Usage: (vec-push! vector object) -> vector

Pushes the provided object onto the end of the vector. This is destructive!

Example:
(def test-push-vec (vec))
(test::assert-equal '(1) (vec-push! test-push-vec 1))
(test::assert-equal '(1) test-push-vec)
(test::assert-equal '(1 2) (vec-push! test-push-vec 2))
(test::assert-equal '(1 2) test-push-vec)
(test::assert-equal '(1 2 3) (vec-push! test-push-vec 3))
(test::assert-equal '(1 2 3) test-push-vec)


vec-remove! Type: Function
root::vec-remove! Usage: (vec-remove! vector index) -> vector

Remove the element at index from vector, shifting all elements after it to the left. This is destructive!

Example:
(def test-remove-nth-vec (vec 1 2 3))
(test::assert-equal '(1 2 3) test-remove-nth-vec)
(vec-remove! test-remove-nth-vec 1)
(test::assert-equal '(1 3) test-remove-nth-vec)
(vec-remove! test-remove-nth-vec 1)
(test::assert-equal '(1) test-remove-nth-vec)
(vec-remove! test-remove-nth-vec 0)
(test::assert-equal '() test-remove-nth-vec)


vec-set! Type: Function
root::vec-set! Usage: (vec-set! vector index value) -> vector

Set the nth index (0 based) of a vector to value. This is destructive! If you need the equivalent operation on a list use setnth!.

Example:
(def test-setnth-vec (vec 1 2 3))
(test::assert-equal '(1 5 3) (vec-set! test-setnth-vec 1 5))
(test::assert-equal '(7 5 3) (vec-set! test-setnth-vec 0 7))
(test::assert-equal '(7 5 9) (vec-set! test-setnth-vec 2 9))


vec-slice Type: Function
root::vec-slice Usage: (vec-slice vector start end?)

Returns a slice of a vector (0 based indexes, end is exclusive).

Example:
(test::assert-equal '(5 6) (vec-slice '#(1 2 3 4 5 6) 4 6))
(test::assert-equal '(1 2 3) (vec-slice '#(1 2 3 4 5 6) 0 3))
(test::assert-equal '(3 4 5) (vec-slice '#(1 2 3 4 5 6) 2 5))
(test::assert-equal '(3 4 5 6) (vec-slice '#(1 2 3 4 5 6) 2))


version: sl-sh 0.9.70 (master:83cd1c9+, release build, linux [x86_64], May 08 2023, 18:47:56 UTC [rustc 1.69.0 (84c898d65 2023-04-16)])