3  Lua Walkthrough

Welcome to the walkthrough of std.lang and it’s interaction with the lua runtime. Ideally, the reader should have at least some experience with both clojure and lua in order to get the most out of the tutorial as the library allows for seamless interop between a clojure runtime and a lua one - whether it is on the server side - node, quickjs, osascript - as well as on the browser and other embedded js environments.

3.1 Setup

Let us briefly explore the std.lang transpiler.

(ns stdlang-book.walkthrough-lua
  (:require [std.lang :as l]))

std.lang can be used in different ways: - generate code for different languages - run the code in different runtimes of those languages

To specify a way to use it, we use l/script. This will create a runtime for evaluation.

^:kind/println
(l/script :lua
  {:require [[xt.lang.base-lib :as k]
             [xt.lang.base-iter :as it]]})
#rt:lang[:lua]

It is now possible to transpile lisp forms to code:

(!.lua
  (+ 1 2 3))
"1 + 2 + 3"

If more than one environment is required, l/script+ is a way to create an annex that

In For example, let us define the following two annexes, named :code and :live.

Here we define :code as a way to use the transpiler to generate Lua code, but not use it in any runtime.

^:kind/println
(l/script+ [:code :lua]
  {:require [[xt.lang.base-lib :as k]
             [xt.lang.base-iter :as it]]})
[#rt:lang[:lua]]

Here we define :live as a way to use the transpiler go generate Lua code, and run it in a Node.lua runtime.

^:kind/println
(l/script+ [:live :lua]
  {:runtime :basic
   :require [[xt.lang.base-lib :as k]
             [xt.lang.base-iter :as it]]})
[#rt.basic[:server/basic :lua r1lmvdv4y2wm 53701 1]]

Let us now use these two ways for basic arithmetic.

[ ;; No runtime, just generating code:
 (l/! [:code] (+ 1 2))
 ;; Generating, running in Node.lua:
 (l/! [:live] (+ 1 2))]
["1 + 2" 3]

4 Types

4.1 Types - Primitives

The seven primitive data types in Lua are string, number, bigint, boolean, undefined, symbol, and null. We work with examples from: https://www.w3docs.com/learn-lua/methods-of-primitives.html

From the Lua Runtime perspective, primitives are extremely important to understand for designing fast programs. They offer the following traits:

  1. Immutability: Once a primitive value is created, it cannot be altered. For instance, when you create a string, you cannot change its individual characters. Any operation that seems to change a primitive actually creates a new primitive. Example:
  2. Memory Efficiency: Primitives are stored directly in the stack memory where the variable is located. This direct storage makes access to primitive values faster and more memory-efficient than objects. Example:
  3. Simple and Fast: Primitives are straightforward in their representation, making them simpler and faster to process compared to objects. They don’t have the overhead of object properties and methods. Example:

4.1.1 Null

form code live
nil nil nil

4.1.2 Undefined

form code live
undefined undefined nil

4.1.3 Boolean

form code live
true true true
false false false

4.1.4 Strings

form code live
"3" '3' "3"
"Hello World" 'Hello World' "Hello World"

4.1.5 Numbers

form code live
3 3 3
1.5 1.5 1.5
1.54444444444444 1.54444444444444 1.5444444444444

4.2 Types - Collection

4.2.1 Arrays

form code live
[1 2 3 4] {1,2,3,4} [1 2 3 4]
["hello" ["world"]] {'hello',{'world'}} ["hello" ["world"]]

4.2.2 Objects

form code live
{:a 1, :b 2, :c 3} {a=1,b=2,c=3} {"a" 1, "b" 2, "c" 3}
{:a {:b {:c 3}}} {a={b={c=3}}} {"a" {"b" {"c" 3}}}

4.2.3 Objects - tab

form code live
(tab ["a" 1] ["b" 2] ["c" 3]) {a=1,b=2,c=3} {"a" 1, "b" 2, "c" 3}

5 Operations

5.1 Operations - Assignment

5.1.1 Var

form code live
(do (var x 1) x) local x = 1 x 1

5.1.2 Reassign

form code live
(do (var x 1) (:= x 10) x) local x = 1 x = 10 x 10

5.2 Operations - Logic

5.2.1 Negation

form code live
(not true) not true false
(not false) not false true
(not 1) not 1 false
(not 0) not 0 false

5.2.2 Or

form code live
(or 0 false) 0 or false 0
(or 1 false) 1 or false 1
(or 0 true) 0 or true 0

5.2.3 And

form code live
(and 0 false) 0 and false false
(and 1 false) 1 and false false
(and 0 true) 0 and true true

5.2.4 Ternary

form code live
(:? true 1 2) true and 1 or 2 1
(:? (or 0 0) 1 2) (0 or 0) and 1 or 2 1

5.3 Operations - Math

5.3.1 Addition

form code live
(+ 1 2 3) 1 + 2 + 3 6
(+ 1 10) 1 + 10 11

5.3.2 Subtraction

form code live
(- 10) -10 -10
(- 10 1.1) 10 - 1.1 8.9
(- 4 3 2 1.1) 4 - 3 - 2 - 1.1 -2.1

5.3.3 Multiplication

form code live
(* 10 20) 10 * 20 200
(* 4 3.3 2.2 1.1) 4 * 3.3 * 2.2 * 1.1 31.944

5.3.4 Division

form code live
(/ 10) 1 / 10 0.1
(/ 10 20) 10 / 20 0.5
(/ 4 3.3 2.2 1.1) 4 / 3.3 / 2.2 / 1.1 0.50087653393439

5.3.5 Pow

form code live
(pow 10 2) 10 ^ 2 100
(pow 0.5 0.2) 0.5 ^ 0.2 0.87055056329612

5.3.6 Mod

form code live
(mod 1123 7) 1123 % 7 3
(mod 1123 7.1) 1123 % 7.1 1.2

5.4 Operations - Comparison

5.4.1 Equals

form code live
(== 1 1) 1 == 1 true
(== 1 "1") 1 == '1' false
(== "hello" "hello") 'hello' == 'hello' true

5.4.2 Not Equals

form code live
(not= 1 2) 1 ~= 2 true
(not= 1 "1") 1 ~= '1' true
(not= "hello" "hello") 'hello' ~= 'hello' false

5.4.3 Less Than

form code live
(< 1 2) 1 < 2 true
(< 1 1) 1 < 1 false

5.4.4 Less Than Equals

form code live
(<= 1 2) 1 <= 2 true
(<= 1 1) 1 <= 1 true

5.4.5 Greater Than

form code live
(> 3 2) 3 > 2 true
(> 3 3) 3 > 3 false

5.4.6 Greater Than Equals

form code live
(>= 3 2) 3 >= 2 true
(>= 3 3) 3 >= 3 true

5.5 Operations - Functions

form code live
(fn [x y] (return (+ x y))) function (x,y) return x + y end function: 0x0102e19808
(do (var hello (fn [x y] (return (+ x y)))) (hello 1 2)) local function hello(x,y) return x + y end hello(1,2) 3

5.6 Operations - Blocks

5.6.1 if block

form code live
(do (var arr [1 2 3 4 5]) (var out) (if (< (x:len arr) 10) (:= out true) (:= out false)) out) local arr = {1,2,3,4,5} local out if #arr < 10 then out = true else out = false end out true

5.6.2 cond block

form code live
(do (var arr [1 2 3 4 5]) (var out) (cond (< (x:len arr) 5) (:= out "1") (< (x:len arr) 10) (:= out "2") :else (:= out "3")) out) local arr = {1,2,3,4,5} local out if #arr < 5 then out = '1' elseif #arr < 10 then out = '2' else out = '3' end out "2"

5.6.3 while block

form code live
(do (var x []) (var i 0) (while (< i 5) (x:arr-push x i) (:= i (+ i 1))) x) local x = {} local i = 0 while i < 5 do table.insert(x,i) i = (i + 1) end x [0 1 2 3 4]

6 Base Lib

6.1 Base Lib - For

6.1.1 for:array

form code live
(do (var out := []) (k/for:array [e [1 2 3 4]] (if (> e 3) (break)) (x:arr-push out e)) out) local out = {} for _, e in ipairs({1,2,3,4}) do if e > 3 then break end table.insert(out,e) end out [1 2 3]

6.1.2 for:object

form code live
(do (var out := []) (var obj := {:a 1, :b 2}) (k/for:object [[k v] obj] (x:arr-push out [k v])) out) local out = {} local obj = {a=1,b=2} for k, v in pairs(obj) do table.insert(out,{k,v}) end out [["a" 1] ["b" 2]]

6.1.3 for:index

form code live
(do (var out := []) (k/for:index [i [0 10 2]] (x:arr-push out i)) out) local out = {} for i = 0,10,2 do table.insert(out,i) end out [0 2 4 6 8 10]

6.1.4 for:return

form code live
(do (var out) (k/for:return [[ret err] (unpack [nil "ERR"])] {:success (:= out ret), :error (:= out err)}) out) local out local ret,err = unpack({nil,'ERR'}) if not err then out = ret else out = err end out "ERR"

6.1.5 for:try

form code live
(do (var out := nil) (k/for:try [[ret err] (do:> (x:err "hello"))] {:success (:= out ret), :error (:= out err)}) out) local out = nil local ok,out = pcall(function () return (function () error('hello') end)() end) if ok then local ret = out out = ret else local err = out out = err end out "[string \"local out = nil...\"]:4: hello"

6.2 Base Lib - Util

6.2.1 invoke

form code live
(k/invoke k/add 1 2) 1 + 2 3

6.2.2 unpack

form code live
[(k/unpack [1 2 3]) (k/unpack [4 5 6])] {unpack({1,2,3}),unpack({4,5,6})} [1 4 5 6]

6.2.3 apply

form code live
(k/apply (fn:> [a b] (+ a b)) [1 2]) (function (a,b) return a + b end)(unpack({1,2})) 3

6.2.4 eval

form code live
(k/eval "1+2") loadstring('return ' .. '1+2')() 3
(k/apply k/eval ["1+2"]) (function (s) return loadstring('return ' .. s)() end)(unpack({'1+2'})) 3

6.2.5 len

form code live
(k/len "1+2") #('1+2') 3
(k/apply k/len ["1+2"]) (function (arr) return #(arr) end)(unpack({'1+2'})) 3

6.2.6 cat

form code live
(k/cat "1+2" "+3") '1+2' .. '+3' "1+2+3"
(k/apply k/cat ["1+2" "+3"]) unpack({'1+2','+3'}) "1+2"

6.2.7 x:del

form code live
(do (var out {:a 1}) (k/x:del (. out ["a"])) out) local out = {a=1} out['a'] = nil out {}

6.2.8 x:shell

form code live
(do (var cb {}) (defn call [] (k/x:shell "ls" cb)) (call)) local cb = {} local function call() local handle = io.popen('ls') local res = handle:read('*a') local f = cb['success'] if f then return f(res) else return res end end call() ""

6.2.9 x:offset

form code live
(k/x:offset) 1 1

6.2.10 x:offset-rev

form code live
(k/x:offset-rev) 0 0

6.2.11 x:offset-len

form code live
(k/x:offset-len 10) 10 10

6.2.12 x:offset-rlen

form code live
(k/x:offset-rlen 10) 9 9

6.2.13 nil?

form code live
(k/nil? "hello") nil == 'hello' false
(k/apply k/nil? ["hello"]) (function (x) return nil == x end)(unpack({'hello'})) false

6.2.14 not-nil?

form code live
(k/not-nil? "hello") nil ~= 'hello' true
(k/apply k/not-nil? ["hello"]) (function (x) return nil ~= x end)(unpack({'hello'})) true

6.2.15 to-string

form code live
(k/to-string 1) tostring(1) "1"
(k/apply k/to-string [1]) (function (obj) return tostring(obj) end)(unpack({1})) "1"

6.2.16 to-number

form code live
(k/to-number "1.1") tonumber('1.1') 1.1
(k/apply k/to-number ["1.1"]) (function (obj) return tonumber(obj) end)(unpack({'1.1'})) 1.1

6.2.17 is-string?

form code live
(k/is-string? "1.1") 'string' == type('1.1') true
(k/apply k/is-string? ["1.1"]) (function (obj) return 'string' == type(obj) end)(unpack({'1.1'})) true

6.2.18 is-number?

form code live
(k/is-number? 1.1) 'number' == type(1.1) true
(k/apply k/is-number? [1.1]) (function (obj) return 'number' == type(obj) end)(unpack({1.1})) true

6.2.19 is-integer?

form code live
(k/is-integer? 1000) 0 == (1000 % 1) true
(k/apply k/is-integer? [1000]) (function (obj) return 0 == (obj % 1) end)(unpack({1000})) true

6.2.20 is-boolean?

form code live
(k/is-boolean? false) 'boolean' == type(false) true
(k/apply k/is-boolean? [false]) (function (obj) return 'boolean' == type(obj) end)(unpack({false})) true

6.2.21 is-function?

form code live
(k/is-function? (fn [] (return 1))) 'function' == type(function () return 1 end) true
(k/apply k/is-function? [(fn [] (return 1))]) (function (x) return 'function' == type(x) end)(unpack({ function () return 1 end })) true

6.2.22 is-array?

form code live
(k/is-array? [1 2 3 4 5]) (('table' == type({1,2,3,4,5})) and (nil ~= ({1,2,3,4,5})[1])) or ('array' == type({1,2,3,4,5})) true
(k/apply k/is-array? [[1 2 3 4 5]]) (function (x) return (('table' == type(x)) and (nil ~= (x)[1])) or ('array' == type(x)) end)(unpack({{1,2,3,4,5}})) true

6.2.23 is-object?

form code live
(k/is-object? {:a 1, :b 2}) (('table' == type({a=1,b=2})) and (nil == ({a=1,b=2})[1])) or ('object' == type({a=1,b=2})) true
(k/apply k/is-object? [{:a 1, :b 2}]) (function (x) return (('table' == type(x)) and (nil == (x)[1])) or ('object' == type(x)) end)(unpack({{a=1,b=2}})) true

6.2.24 type-native

form code live
(do [(k/type-native {}) (k/type-native [1]) (k/type-native (fn [])) (k/type-native 1) (k/type-native "") (k/type-native true)]) { k.type_native({}), k.type_native({1}), k.type_native(function () end), k.type_native(1), k.type_native(''), k.type_native(true) } ["object" "array" "function" "number" "string" "boolean"]

6.2.25 type-class

form code live
(do [(k/type-class {}) (k/type-class [1]) (k/type-class (fn [])) (k/type-class 1) (k/type-class "") (k/type-class true)]) { k.type_class({}), k.type_class({1}), k.type_class(function () end), k.type_class(1), k.type_class(''), k.type_class(true) } ["object" "array" "function" "number" "string" "boolean"]

6.2.26 print

form code live
(k/print "hello") print('hello') nil
(k/apply k/print ["hello"]) print(unpack({'hello'})) nil

6.2.27 random

form code live
(k/random) math.random() 0.74451774485697
(k/apply k/random []) (function () return math.random() end)(unpack({})) 0.55329655868909

6.2.28 now-ms

form code live
(k/now-ms) math.floor(1000 * os.time()) 1745742157000
(k/apply k/now-ms []) (function () return math.floor(1000 * os.time()) end)(unpack({})) 1745742157000

6.3 Base Lib - Global

6.3.1 !:G

Accesses the global object

form code live
(!:G CUSTOM) CUSTOM nil

6.3.2 global-set

form code live
(do (k/global-set "HELLO" 1) (!:G HELLO)) HELLO = 1 HELLO 1

6.3.3 global-has?

form code live
(do (k/global-set "HELLO" 1) (k/global-has? "HELLO")) HELLO = 1 HELLO ~= nil true

6.3.4 global-del

form code live
(do (k/global-del "HELLO") (k/global-has? "HELLO")) HELLO = nil HELLO ~= nil false

6.4 Base Lib - String

6.4.1 get-char

form code live
(k/get-char "abc" 0) string.byte('abc',0) nil
(k/apply k/get-char ["abc" 0]) (function (s,i) return string.byte(s,i) end)(unpack({'abc',0})) nil

6.4.2 gt-string

form code live
[(k/gt-string "a" "b") (k/gt-string "A" "a")] {'b' < 'a','a' < 'A'} [false false]

6.4.3 lt-string

form code live
[(k/lt-string "a" "b") (k/lt-string "A" "a")] {'a' < 'b','A' < 'a'} [true true]

6.4.4 split

form code live
(k/split "hello/world" "/") (function (s,tok) local out = {} string.gsub(s,string.format('([^%s]+)',tok),function (c) table.insert(out,c) end) return out end)('hello/world','/') ["hello" "world"]
(k/apply k/split ["hello/world" "/"]) (function (s,tok) return (function (s,tok) local out = {} string.gsub(s,string.format('([^%s]+)',tok),function (c) table.insert(out,c) end) return out end)(s,tok) end)(unpack({'hello/world','/'})) ["hello" "world"]

6.4.5 join

form code live
(k/join "/" ["hello" "world"]) table.concat({'hello','world'},'/') "hello/world"
(k/apply k/join ["/" ["hello" "world"]]) (function (s,arr) return table.concat(arr,s) end)(unpack({'/',{'hello','world'}})) "hello/world"

6.4.6 replace

form code live
(k/replace "hello/world" "/" "_") string.gsub('hello/world','/','_') "hello_world"
(k/apply k/replace ["hello/world" "/" "_"]) (function (s,tok,replacement) return string.gsub(s,tok,replacement) end)(unpack({'hello/world','/','_'})) "hello_world"

6.4.7 index-of

form code live
(k/index-of "hello/world" "/") (string.find('hello/world','/') or -1) - 1 5
(k/apply k/index-of ["hello/world" "/"]) (function (s,tok) return (string.find(s,tok) or -1) - 1 end)(unpack({'hello/world','/'})) 5

6.4.8 substring

form code live
[(k/substring "hello/world" 3) (k/substring "hello/world" 3 8)] {string.sub('hello/world',4),string.sub('hello/world',4,8)} ["lo/world" "lo/wo"]

6.4.9 to-uppercase

form code live
(k/to-uppercase "hello") string.upper('hello') "HELLO"
(k/apply k/to-uppercase ["hello"]) (function (s) return string.upper(s) end)(unpack({'hello'})) "HELLO"

6.4.10 to-lowercase

form code live
(k/to-lowercase "hello") string.lower('hello') "hello"
(k/apply k/to-lowercase ["hello"]) (function (s) return string.lower(s) end)(unpack({'hello'})) "hello"

6.4.11 to-fixed

form code live
(k/to-fixed 1.2 3) string.format('%.' .. 3 .. 'f',1.2) "1.200"
(k/apply k/to-fixed [1.2 3]) (function (n,digits) return string.format('%.' .. digits .. 'f',n) end)(unpack({1.2,3})) "1.200"

6.4.12 trim

form code live
(k/trim " \n hello \n ") string.gsub(' \n hello \n ','^%s*(.-)%s*$','%1') "hello"
(k/apply k/trim [" \n hello \n "]) (function (s) return string.gsub(s,'^%s*(.-)%s*$','%1') end)(unpack({' \n hello \n '})) "hello"

6.4.13 trim-left

form code live
(k/trim-left " \n hello \n ") string.gsub(' \n hello \n ','^%s*','') "hello \n "
(k/apply k/trim-left [" \n hello \n "]) (function (s) return string.gsub(s,'^%s*','') end)(unpack({' \n hello \n '})) "hello \n "

6.4.14 trim-right

form code live
(k/trim-right " \n hello \n ") string.gsub(' \n hello \n ','^(%s*.-)%s*$','%1') " \n hello"
(k/apply k/trim-right [" \n hello \n "]) (function (s) return string.gsub(s,'^(%s*.-)%s*$','%1') end)(unpack({' \n hello \n '})) " \n hello"

6.4.15 starts-with?

form code live
(k/starts-with? "Foo Bar" "Foo") k.starts_withp('Foo Bar','Foo') true

6.4.16 ends-with?

form code live
(k/ends-with? "Foo Bar" "Bar") k.ends_withp('Foo Bar','Bar') true

6.4.17 capitalize

form code live
(k/capitalize "hello") k.capitalize('hello') "Hello"

6.4.18 decapitalize

form code live
(k/decapitalize "HELLO") k.decapitalize('HELLO') "hELLO"

6.4.19 pad-left

form code live
(k/pad-left "000" 5 "-") k.pad_left('000',5,'-') "--000"

6.4.20 pad-right

form code live
(k/pad-right "000" 5 "-") k.pad_right('000',5,'-') "000--"

6.4.21 pad-lines

form code live
(k/pad-lines (k/join "\n" ["hello" "world"]) 2 " ") k.pad_lines(table.concat({'hello','world'},'\n'),2,' ') " hello\n world"

6.4.22 split-long

form code live
(k/split-long "1234567890123456789012345678901234567890123456789012345678901234567890" 4) k.split_long( '1234567890123456789012345678901234567890123456789012345678901234567890', 4 ) ["1234" "5678" "9012" "3456" "7890" "1234" "5678" "9012" "3456" "7890" "1234" "5678" "9012" "3456" "7890" "1234" "5678" "90"]

6.5 Base Lib - Encode

6.5.1 js-encode

form code live
(k/js-encode [1 2 {:a [{:b 3}]}]) cjson.encode({1,2,{a={{b=3}}}}) "[1,2,{\"a\":[{\"b\":3}]}]"
(k/apply k/js-encode [[1 2 {:a [{:b 3}]}]]) (function (obj) return cjson.encode(obj) end)(unpack({{1,2,{a={{b=3}}}}})) "[1,2,{\"a\":[{\"b\":3}]}]"

6.5.2 js-decode

form code live
(k/js-decode "[1,2,{\"a\":[{\"b\":3}]}]") cjson.decode('[1,2,{"a":[{"b":3}]}]') [1 2 {"a" [{"b" 3}]}]
(k/apply k/js-decode ["[1,2,{\"a\":[{\"b\":3}]}]"]) (function (s) return cjson.decode(s) end)(unpack({'[1,2,{"a":[{"b":3}]}]'})) [1 2 {"a" [{"b" 3}]}]

6.5.3 json-push

form code live
(k/json-push "[1,2,3]" "4") string.sub('[1,2,3]',1,#'[1,2,3]' - 1) .. ',' .. '4' .. ']' "[1,2,3,4]"
(k/apply k/json-push ["[1,2,3]" "4"]) (function (json,e) return string.sub(json,1,#json - 1) .. ',' .. e .. ']' end)(unpack({'[1,2,3]','4'})) "[1,2,3,4]"

6.5.4 json-push-first

form code live
(k/json-push-first "[1,2,3]" "0") '[' .. '0' .. ',' .. string.sub('[1,2,3]',2) "[0,1,2,3]"
(k/apply k/json-push-first ["[1,2,3]" "0"]) (function (json,e) return '[' .. e .. ',' .. string.sub(json,2) end)(unpack({'[1,2,3]','0'})) "[0,1,2,3]"

6.6 Base Lib - Symbol

6.6.1 sym-full

form code live
(k/sym-full "hello" "world") k.sym_full('hello','world') "hello/world"

6.6.2 sym-name

form code live
(k/sym-name "hello/world") k.sym_name('hello/world') "world"

6.6.3 sym-ns

form code live
[(k/sym-ns "hello/world") (k/sym-ns "hello")] k.sym_ns('hello/world'),k.sym_ns('hello') "hello"

6.6.4 sym-pair

form code live
(k/sym-pair "hello/world") k.sym_pair('hello/world') ["hello" "world"]

7 Base Lib - Math

7.1 Base Lib - Math Basic

7.1.1 eq

form code live
[(k/eq 2 2) (k/eq 2 1)] {2 == 2,2 == 1} [true false]
(k/apply k/eq [1 1]) (function (a,b) return a == b end)(unpack({1,1})) true

7.1.2 neq

form code live
[(k/neq 2 2) (k/neq 2 1)] {2 ~= 2,2 ~= 1} [false true]
(k/apply k/neq [1 1]) (function (a,b) return a ~= b end)(unpack({1,1})) false

7.1.3 add

form code live
(k/add 1 2) 1 + 2 3
(k/apply k/add [1 2]) (function (a,b) return a + b end)(unpack({1,2})) 4

7.1.4 sub

form code live
(k/sub 1 2) 1 - 2 -1
(k/apply k/sub [1 2]) (function (a,b) return a - b end)(unpack({1,2})) -1

7.1.5 mul

form code live
(k/mul 10 10) 10 * 10 100
(k/apply k/mul [1 2]) (function (a,b) return a * b end)(unpack({1,2})) 2

7.1.6 div

form code live
(k/div 10 2) 10 / 2 5
(k/apply k/div [1 2]) (function (a,b) return a / b end)(unpack({1,2})) 0.5

7.1.7 gt

form code live
[(k/gt 2 2) (k/gt 2 1)] {2 > 2,2 > 1} [false true]
(k/apply k/gt [1 2]) (function (a,b) return a > b end)(unpack({1,2})) false

7.1.8 lt

form code live
[(k/lt 2 2) (k/lt 1 2)] {2 < 2,1 < 2} [false true]
(k/apply k/lt [1 2]) (function (a,b) return a < b end)(unpack({1,2})) true

7.1.9 gte

form code live
[(k/gte 2 2) (k/gte 2 1)] {2 >= 2,2 >= 1} [true true]
(k/apply k/gte [1 2]) (function (a,b) return a >= b end)(unpack({1,2})) false

7.1.10 lte

form code live
[(k/lte 2 2) (k/lte 1 2)] {2 <= 2,1 <= 2} [true true]
(k/apply k/lte [1 2]) (function (a,b) return a <= b end)(unpack({1,2})) true

7.1.11 neg

form code live
[(k/neg 1) (k/neg 0) (k/neg -1)] {-(1),-(0),-(-1)} [-1 0 1]
(k/apply k/neg [1]) (function (x) return -(x) end)(unpack({1})) -1

7.1.12 inc

form code live
(k/inc 1) 1 + 1 2
(k/apply k/inc [1]) (function (x) return x + 1 end)(unpack({1})) 2

7.1.13 dec

form code live
(k/dec 1) 1 - 1 0
(k/apply k/dec [1]) (function (x) return x - 1 end)(unpack({1})) 0

7.1.14 pow

form code live
(k/pow 2 3) math.pow(2,3) 8
(k/apply k/pow [5 6]) (function (base,n) return math.pow(base,n) end)(unpack({5,6})) 15625

7.1.15 quot

form code live
(k/quot 20 3) math.floor(20 / 3) 6
(k/apply k/quot [50 6]) (function (base,n) return math.floor(base / n) end)(unpack({50,6})) 8

7.1.16 sqrt

form code live
[(k/sqrt -1) (k/sqrt 1)] {math.sqrt(-1),math.sqrt(1)} table: 0x0102e08fe8
(k/apply k/sqrt [16]) (function (num) return math.sqrt(num) end)(unpack({16})) 4

7.1.17 exp

form code live
(k/exp 3) math.exp(3) 20.085536923188
(k/apply k/exp [6]) (function (num) return math.exp(num) end)(unpack({6})) 403.42879349274

7.1.18 loge

form code live
(k/loge 3) math.log(3) 1.0986122886681
(k/apply k/loge [6]) (function (num) return math.log(num) end)(unpack({6})) 1.7917594692281

7.1.19 log10

form code live
(k/log10 3) math.log10(3) 0.47712125471966
(k/apply k/log10 [6]) (function (num) return math.log10(num) end)(unpack({6})) 0.77815125038364

7.1.20 mod

form code live
(k/mod 20 3) 20 % 3 2
(k/apply k/mod [50 6]) (function (num,denom) return num % denom end)(unpack({50,6})) 2

7.1.21 mod-pos

form code live
[(mod -11 10) (k/mod-pos -11 10)] {-11 % 10,k.mod_pos(-11,10)} [9 9]

7.1.22 mod-offset

form code live
[(k/mod-offset 20 280 360) (k/mod-offset 280 20 360) (k/mod-offset 280 -80 360) (k/mod-offset 20 -60 360) (k/mod-offset 60 30 360)] { k.mod_offset(20,280,360), k.mod_offset(280,20,360), k.mod_offset(280,-80,360), k.mod_offset(20,-60,360), k.mod_offset(60,30,360) } [-100 100 0 -80 -30]

7.2 Base Lib - Math Checks

7.2.1 zero?

form code live
[(k/zero? 1) (k/zero? 0)] {1 == 0,0 == 0} [false true]
(k/apply k/zero? [1]) (function (x) return x == 0 end)(unpack({1})) false

7.2.2 pos?

form code live
[(k/pos? 1) (k/pos? 0)] {1 > 0,0 > 0} [true false]
(k/apply k/pos? [-1]) (function (x) return x > 0 end)(unpack({-1})) false

7.2.3 neg?

form code live
[(k/neg? -1) (k/neg? 0)] {-1 < 0,0 < 0} [true false]
(k/apply k/neg? [-1]) (function (x) return x < 0 end)(unpack({-1})) true

7.2.4 even?

form code live
[(k/even? 2) (k/even? 1)] {0 == (2 % 2),0 == (1 % 2)} [true false]
(k/apply k/even? [-1]) (function (x) return 0 == (x % 2) end)(unpack({-1})) false

7.2.5 odd?

form code live
[(k/odd? 2) (k/odd? 1)] {not (0 == (2 % 2)),not (0 == (1 % 2))} [false true]
(k/apply k/odd? [-1]) (function (x) return not (0 == (x % 2)) end)(unpack({-1})) true

7.3 Base Lib - Math Util

7.3.1 abs

form code live
[(k/abs -1) (k/abs 1)] {math.abs(-1),math.abs(1)} [1 1]
(k/apply k/abs [-1]) (function (num) return math.abs(num) end)(unpack({-1})) 1

7.3.2 max

form code live
(k/max 1 2 3 2) math.max(1,2,3,2) 3
(k/apply k/max [1 2 3 2]) math.max(unpack({1,2,3,2})) 3

7.3.3 min

form code live
(k/min 1 2 3 2) math.min(1,2,3,2) 1
(k/apply k/min [1 2 3 2]) math.max(unpack({1,2,3,2})) 3

7.3.4 ceil

form code live
[(k/ceil -1.1) (k/ceil 1.1)] {math.ceil(-1.1),math.ceil(1.1)} [-1 2]
(k/apply k/ceil [-1.1]) (function (num) return math.ceil(num) end)(unpack({-1.1})) -1

7.3.5 floor

form code live
[(k/floor -1.1) (k/floor 1.1)] {math.floor(-1.1),math.floor(1.1)} [-2 1]
(k/apply k/floor [-1.1]) (function (num) return math.floor(num) end)(unpack({-1.1})) -2

7.3.6 gcd

form code live
(k/gcd 10 6) k.gcd(10,6) 2

7.3.7 lcm

form code live
(k/lcm 10 6) k.lcm(10,6) 30

7.3.8 mix

form code live
(k/mix 100 20 0.1) k.mix(100,20,0.1) 92

7.3.9 sign

form code live
[(k/sign -10) (k/sign 10)] {k.sign(-10),k.sign(10)} [-1 1]

7.3.10 round

form code live
[(k/round 0.9) (k/round 1.1) (k/round 1.49) (k/round 1.51)] {k.round(0.9),k.round(1.1),k.round(1.49),k.round(1.51)} [1 1 1 2]

7.3.11 clamp

form code live
[(k/clamp 0 5 6) (k/clamp 0 5 -1) (k/clamp 0 5 4)] {k.clamp(0,5,6),k.clamp(0,5,-1),k.clamp(0,5,4)} [5 0 4]

7.4 Base Lib - Math Bitwise

7.4.1 bit-and

form code live
(k/bit-and 7 4) bit.band(7,4) 4
(k/apply k/bit-and [7 4]) (function (a,b) return bit.band(a,b) end)(unpack({7,4})) 4

7.4.2 bit-or

form code live
(k/bit-or 3 4) bit.bor(3,4) 7
(k/apply k/bit-or [3 4]) (function (a,b) return bit.bor(a,b) end)(unpack({3,4})) 7

7.4.3 bit-xor

form code live
(k/bit-xor 3 5) bit.bxor(3,5) 6
(k/apply k/bit-xor [3 5]) (function (a,b) return bit.bxor(a,b) end)(unpack({3,5})) 6

7.4.4 bit-lshift

form code live
(k/bit-lshift 7 1) bit.lshift(7,1) 14
(k/apply k/bit-lshift [7 1]) (function (x,n) return bit.lshift(x,n) end)(unpack({7,1})) 14

7.4.5 bit-rshift

form code live
(k/bit-rshift 7 1) bit.rshift(7,1) 3
(k/apply k/bit-rshift [7 1]) (function (x,n) return bit.rshift(x,n) end)(unpack({7,1})) 3

7.4.6 bit-count

form code live
[(k/bit-count 16) (k/bit-count 10) (k/bit-count 3) (k/bit-count 7)] {k.bit_count(16),k.bit_count(10),k.bit_count(3),k.bit_count(7)} [1 2 2 3]

7.5 Base Lib - Math Trigonometry

7.5.1 sin

form code live
[(k/sin (/ 3.14159 4)) (k/sin (/ 3.14159 6))] {math.sin(3.14159 / 4),math.sin(3.14159 / 6)} [0.70710631209356 0.49999961698726]
(k/apply k/sin [(/ 3.14159 4)]) (function (num) return math.sin(num) end)(unpack({3.14159 / 4})) 0.70710631209356

7.5.2 cos

form code live
[(k/cos (/ 3.14159 4)) (k/cos (/ 3.14159 6))] {math.cos(3.14159 / 4),math.cos(3.14159 / 6)} [0.70710725027923 0.86602562491684]
(k/apply k/cos [(/ 3.14159 4)]) (function (num) return math.cos(num) end)(unpack({3.14159 / 4})) 0.70710725027923

7.5.3 tan

form code live
[(k/tan (/ 3.14159 4)) (k/tan (/ 3.14159 6))] {math.tan(3.14159 / 4),math.tan(3.14159 / 6)} [0.99999867320598 0.57734967950316]
(k/apply k/tan [(/ 3.14159 4)]) (function (num) return math.tan(num) end)(unpack({3.14159 / 4})) 0.99999867320598

7.5.4 asin

form code live
[(k/asin 0.5) (k/asin 0.8)] {math.asin(0.5),math.asin(0.8)} [0.5235987755983 0.92729521800161]
(k/apply k/asin [0.5]) (function (num) return math.asin(num) end)(unpack({0.5})) 0.5235987755983

7.5.5 acos

form code live
[(k/acos 0.5) (k/acos 0.8)] {math.acos(0.5),math.acos(0.8)} [1.0471975511966 0.64350110879328]
(k/apply k/acos [0.5]) (function (num) return math.acos(num) end)(unpack({0.5})) 1.0471975511966

7.5.6 atan

form code live
[(k/atan 0.5) (k/atan 0.8)] {math.atan(0.5),math.atan(0.8)} [0.46364760900081 0.67474094222355]
(k/apply k/atan [0.5]) (function (num) return math.atan(num) end)(unpack({0.5})) 0.46364760900081

7.5.7 sinh

form code live
[(k/sinh (/ 3.14159 4)) (k/sinh (/ 3.14159 6))] {math.sinh(3.14159 / 4),math.sinh(3.14159 / 6)} [0.86867008274391 0.54785296960063]
(k/apply k/sinh [(/ 3.14159 4)]) (function (num) return math.sinh(num) end)(unpack({3.14159 / 4})) 0.86867008274391

7.5.8 cosh

form code live
[(k/cosh (/ 3.14159 4)) (k/cosh (/ 3.14159 6))] {math.cosh(3.14159 / 4),math.cosh(3.14159 / 6)} [1.3246085129782 1.1402380787801]
(k/apply k/cosh [(/ 3.14159 4)]) (function (num) return math.cosh(num) end)(unpack({3.14159 / 4})) 1.3246085129782

7.5.9 tanh

form code live
[(k/tanh (/ 3.14159 4)) (k/tanh (/ 3.14159 6))] {math.tanh(3.14159 / 4),math.tanh(3.14159 / 6)} [0.65579382453977 0.48047243799009]
(k/apply k/tanh [(/ 3.14159 4)]) (function (num) return math.tanh(num) end)(unpack({3.14159 / 4})) 0.65579382453977

8 Base Lib - Collection

8.1 Base Lib - Sequence

8.1.1 first

form code live
(k/first [1 2 3]) ({1,2,3})[1] 1
(k/apply [k/first [[1 2 3]]]) (function (arr) return arr[1] end)(unpack({{1,2,3}})) 1

8.1.2 second

form code live
(k/second [1 2 3]) ({1,2,3})[2] 2
(k/apply [k/second [[1 2 3]]]) (function (arr) return arr[2] end)(unpack({{1,2,3}})) 2

8.1.3 nth

form code live
(k/nth [1 2 3] 2) ({1,2,3})[3] 3
(k/apply [k/nth [[1 2 3] 2]]) (function (arr,i) return arr[i + 1] end)(unpack({{1,2,3},2})) 3

8.1.4 last

form code live
(k/last [1 2 3]) ({1,2,3})[#{1,2,3} + 0] 3
(k/apply [k/last [[1 2 3]]]) (function (arr) return arr[#arr + 0] end)(unpack({{1,2,3}})) 3

8.1.5 second-last

form code live
(k/second-last [1 2 3]) ({1,2,3})[#{1,2,3} + -1] 2
(k/apply [k/second-last [[1 2 3]]]) (function (arr) return arr[#arr + -1] end)(unpack({{1,2,3}})) 2

8.1.6 get-idx

form code live
[(k/get-idx [1 2 3] 1) (k/get-idx [1 2 3] 2)] {({1,2,3})[1],({1,2,3})[2]} [1 2]
(k/apply k/get-idx [[1 2 3] 1]) (function (arr,i,d) return arr[i] or d end)(unpack({{1,2,3},1})) 1

8.1.7 set-idx

form code live
(do (var out := [1 2 3 4 5]) (k/set-idx out 2 5) out) local out = {1,2,3,4,5} out[2] = 5 out [1 5 3 4 5]

8.1.8 is-empty?

form code live
[(k/is-empty? nil) (k/is-empty? "") (k/is-empty? "123") (k/is-empty? []) (k/is-empty? [1 2 3]) (k/is-empty? {}) (k/is-empty? {:a 1, :b 2})] { k.is_emptyp(nil), k.is_emptyp(''), k.is_emptyp('123'), k.is_emptyp({}), k.is_emptyp({1,2,3}), k.is_emptyp({}), k.is_emptyp({a=1,b=2}) } [true true false true false true false]

8.2 Base Lib - Keys

8.2.1 has-key?

form code live
[(k/has-key? {:a 1} "a") (k/has-key? {:a 1} "b")] {({a=1})['a'] ~= nil,({a=1})['b'] ~= nil} [true false]
(k/apply k/has-key? [{:a 1} "a"]) (function (obj,k) return obj[k] ~= nil end)(unpack({{a=1},'a'})) true

8.2.2 del-key

form code live
(do (var out := {:a 1, :b 2}) (k/del-key out "a") out) local out = {a=1,b=2} out['a'] = nil out {"b" 2}

8.2.3 get-key

form code live
[(k/get-key {:a 1} "a") (k/get-key {:a 1} "b")] {({a=1})['a'],({a=1})['b']} [1]
(k/apply k/get-key [{:a 1} "a"]) (function (obj,k,d) return obj[k] or d end)(unpack({{a=1},'a'})) 1
(k/apply k/get-key [{:a 1} "b" 2]) (function (obj,k,d) return obj[k] or d end)(unpack({{a=1},'b',2})) 2

8.2.4 get-path

form code live
[(k/get-path {:a {:b {:c 1}}} ["a" "b" "c"]) (k/get-path {:a 1} ["b"] 2)] {({a={b={c=1}}})['a']['b']['c'],({a=1})['b'] or 2} [1 2]

8.2.5 set-key

form code live
(do (var out := {:a 1, :b 2}) (k/set-key out "a" 5) out) local out = {a=1,b=2} out['a'] = 5 out {"a" 5, "b" 2}

8.2.6 copy-key

form code live
(do (var out := {}) (k/copy-key out {:a 1} "a") out) local out = {} out['a'] = ({a=1})['a'] out {"a" 1}
(do (var out := {}) (k/copy-key out {:a 1} ["c" "a"]) out) local out = {} out['c'] = ({a=1})['a'] out {"c" 1}

8.2.7 swap-key

form code live
(do (var out := {:a 1, :b 2}) (k/swap-key out "a" k/inc) out) local out = {a=1,b=2} out['a'] = (out['a'] + 1) out {"a" 2, "b" 2}

8.3 Base Lib - Array

8.3.1 x:arr-push

form code live
(do (var out [1 2 3]) (k/x:arr-push out 4) out) local out = {1,2,3} table.insert(out,4) out [1 2 3 4]

8.3.2 x:arr-pop

form code live
(do (var out [1 2 3]) (k/x:arr-pop out) out) local out = {1,2,3} table.remove(out) out [1 2]

8.3.3 x:arr-push-first

form code live
(do (var out [1 2 3]) (k/x:arr-push-first out 0) out) local out = {1,2,3} table.insert(out,1,0) out [0 1 2 3]

8.3.4 x:arr-pop-first

form code live
(do (var out [1 2 3]) (k/x:arr-pop-first out) out) local out = {1,2,3} table.remove(out,1) out [2 3]

8.3.5 x:arr-insert

form code live
(do (var out [1 2 3]) (k/x:arr-insert out (x:offset 2) "a") out) local out = {1,2,3} table.insert(out,3,'a') out [1 2 "a" 3]

8.3.6 arr-lookup

form code live
(k/arr-lookup ["a" "b" "c"]) k.arr_lookup({'a','b','c'}) {"a" true, "b" true, "c" true}

8.3.7 arr-every

form code live
[(k/arr-every [1 2 3] k/odd?) (k/arr-every [1 3] k/odd?)] { k.arr_every({1,2,3},function (x) return not (0 == (x % 2)) end), k.arr_every({1,3},function (x) return not (0 == (x % 2)) end) } [false true]

8.3.8 arr-some

form code live
[(k/arr-some [1 2 3] k/even?) (k/arr-some [1 3] k/even?)] { k.arr_some({1,2,3},function (x) return 0 == (x % 2) end), k.arr_some({1,3},function (x) return 0 == (x % 2) end) } [true false]

8.3.9 arr-each

form code live
(do (var out []) (k/arr-each [1 2 3 4 5] (fn [e] (x:arr-push out (+ 1 e)))) out) local out = {} k.arr_each({1,2,3,4,5},function (e) table.insert(out,1 + e) end) out [2 3 4 5 6]

8.3.10 arr-omit

form code live
(k/arr-omit ["a" "b" "c" "d"] 2) k.arr_omit({'a','b','c','d'},2) ["a" "b" "d"]

8.3.11 arr-reverse

form code live
(k/arr-reverse [1 2 3 4 5]) k.arr_reverse({1,2,3,4,5}) [5 4 3 2 1]

8.3.12 arr-find

form code live
(k/arr-find [1 2 3 4 5] (fn:> [x] (== x 3))) k.arr_find({1,2,3,4,5},function (x) return x == 3 end) 2

8.3.13 arr-zip

form code live
(k/arr-zip ["a" "b" "c"] [1 2 3]) k.arr_zip({'a','b','c'},{1,2,3}) {"a" 1, "b" 2, "c" 3}

8.3.14 arr-map

form code live
(k/arr-map [1 2 3 4 5] k/inc) k.arr_map({1,2,3,4,5},function (x) return x + 1 end) [2 3 4 5 6]

8.3.15 arr-clone

form code live
(k/arr-clone [1 2 3]) k.arr_clone({1,2,3}) [1 2 3]

8.3.16 arr-append

form code live
(do (var out [1 2 3]) (k/arr-append out [4 5]) out) local out = {1,2,3} k.arr_append(out,{4,5}) out [1 2 3 4 5]

8.3.17 arr-slice

form code live
(k/arr-slice [1 2 3 4 5] 1 3) k.arr_slice({1,2,3,4,5},1,3) [2 3]

8.3.18 arr-rslice

form code live
(k/arr-rslice [1 2 3 4 5] 1 3) k.arr_rslice({1,2,3,4,5},1,3) [3 2]

8.3.19 arr-tail

form code live
(k/arr-tail [1 2 3 4 5] 3) k.arr_tail({1,2,3,4,5},3) [5 4 3]

8.3.20 arr-mapcat

form code live
(k/arr-mapcat [1 2 3] (fn:> [k] [k k k])) k.arr_mapcat({1,2,3},function (k) return {k,k,k} end) [1 1 1 2 2 2 3 3 3]

8.3.21 arr-partition

form code live
(k/arr-partition [1 2 3 4 5 6 7 8 9 10] 3) k.arr_partition({1,2,3,4,5,6,7,8,9,10},3) [[1 2 3] [4 5 6] [7 8 9] [10]]

8.3.22 arr-filter

form code live
(k/arr-filter [1 2 3 4 5] k/odd?) k.arr_filter({1,2,3,4,5},function (x) return not (0 == (x % 2)) end) [1 3 5]

8.3.23 arr-keep

form code live
(k/arr-keep [1 2 3 4 5] (fn:> [x] (:? (k/odd? x) x))) k.arr_keep({1,2,3,4,5},function (x) return not (0 == (x % 2)) and x or nil end) [1 3 5]

8.3.24 arr-keepf

form code live
(k/arr-keepf [1 2 3 4 5] k/odd? k/identity) k.arr_keepf({1,2,3,4,5},function (x) return not (0 == (x % 2)) end,k.identity) [1 3 5]

8.3.25 arr-juxt

form code live
(k/arr-juxt [["a" 1] ["b" 2] ["c" 3]] k/first k/second) k.arr_juxt({{'a',1},{'b',2},{'c',3}},function (arr) return arr[1] end,function (arr) return arr[2] end) {"a" 1, "b" 2, "c" 3}

8.3.26 arr-foldl

form code live
(k/arr-foldl [1 2 3 4 5] k/add 0) k.arr_foldl({1,2,3,4,5},function (a,b) return a + b end,0) 15

8.3.27 arr-foldr

form code live
(k/arr-foldr [1 2 3 4 5] k/step-push []) k.arr_foldr({1,2,3,4,5},k.step_push,{}) [5 4 3 2 1]

8.3.28 arr-pipel

form code live
(k/arr-pipel [(fn:> [x] (* x 10)) (fn:> [x] (+ x 10))] 1) k.arr_pipel({ function (x) return x * 10 end, function (x) return x + 10 end },1) 20

8.3.29 arr-piper

form code live
(k/arr-piper [(fn:> [x] (* x 10)) (fn:> [x] (+ x 10))] 1) k.arr_piper({ function (x) return x * 10 end, function (x) return x + 10 end },1) 110

8.3.30 arr-group-by

form code live
(k/arr-group-by [["a" 1] ["a" 2] ["b" 3] ["b" 4]] k/first k/second) k.arr_group_by({{'a',1},{'a',2},{'b',3},{'b',4}},function (arr) return arr[1] end,function (arr) return arr[2] end) {"a" [1 2], "b" [3 4]}

8.3.31 arr-range

form code live
[(k/arr-range 10) (k/arr-range [10]) (k/arr-range [2 8]) (k/arr-range [2 9 2])] { k.arr_range(10), k.arr_range({10}), k.arr_range({2,8}), k.arr_range({2,9,2}) } [[0 1 2 3 4 5 6 7 8 9] [0 1 2 3 4 5 6 7 8 9] [2 3 4 5 6 7] [2 4 6 8]]

8.3.32 arr-intersection

form code live
(k/arr-intersection ["a" "b" "c" "d"] ["c" "d" "e" "f"]) k.arr_intersection({'a','b','c','d'},{'c','d','e','f'}) ["c" "d"]

8.3.33 arr-difference

form code live
(k/arr-difference ["a" "b" "c" "d"] ["c" "d" "e" "f"]) k.arr_difference({'a','b','c','d'},{'c','d','e','f'}) ["e" "f"]

8.3.34 arr-union

form code live
(k/arr-union ["a" "b" "c" "d"] ["c" "d" "e" "f"]) k.arr_union({'a','b','c','d'},{'c','d','e','f'}) ["f" "e" "a" "b" "c" "d"]

8.3.35 arr-sort

form code live
[(k/arr-sort [3 4 1 2] k/identity (fn:> [a b] (< a b))) (k/arr-sort [3 4 1 2] k/identity (fn:> [a b] (< b a))) (k/arr-sort [["c" 3] ["d" 4] ["a" 1] ["b" 2]] k/first (fn:> [a b] (x:arr-str-comp a b))) (k/arr-sort [["c" 3] ["d" 4] ["a" 1] ["b" 2]] k/second (fn:> [a b] (< a b)))] { k.arr_sort({3,4,1,2},k.identity,function (a,b) return a < b end), k.arr_sort({3,4,1,2},k.identity,function (a,b) return b < a end), k.arr_sort({{'c',3},{'d',4},{'a',1},{'b',2}},function (arr) return arr[1] end,function (a,b) return a < b end), k.arr_sort({{'c',3},{'d',4},{'a',1},{'b',2}},function (arr) return arr[2] end,function (a,b) return a < b end) } [[1 2 3 4] [4 3 2 1] [["a" 1] ["b" 2] ["c" 3] ["d" 4]] [["a" 1] ["b" 2] ["c" 3] ["d" 4]]]

8.3.36 arr-sorted-merge

form code live
[(k/arr-sorted-merge [1 2 3] [4 5 6] k/lt) (k/arr-sorted-merge [1 2 4] [3 5 6] k/lt) (k/arr-sorted-merge (k/arr-reverse [1 2 4]) (k/arr-reverse [3 5 6]) k/gt)] { k.arr_sorted_merge({1,2,3},{4,5,6},function (a,b) return a < b end), k.arr_sorted_merge({1,2,4},{3,5,6},function (a,b) return a < b end), k.arr_sorted_merge(k.arr_reverse({1,2,4}),k.arr_reverse({3,5,6}),function (a,b) return a > b end) } [[1 2 3 4 5 6] [1 2 3 4 5 6] [6 5 4 3 2 1]]

8.3.37 arr-shuffle

form code live
(k/arr-shuffle [1 2 3 4 5]) k.arr_shuffle({1,2,3,4,5}) [3 1 4 5 2]

8.3.38 arr-pushl

form code live
[(k/arr-pushl [1 2 3 4] 5 100) (k/arr-pushl [1 2 3 4] 5 4)] {k.arr_pushl({1,2,3,4},5,100),k.arr_pushl({1,2,3,4},5,4)} [[1 2 3 4 5] [2 3 4 5]]

8.3.39 arr-pushr

form code live
[(k/arr-pushr [1 2 3 4] 5 100) (k/arr-pushr [1 2 3 4] 5 4)] {k.arr_pushr({1,2,3,4},5,100),k.arr_pushr({1,2,3,4},5,4)} [[5 1 2 3 4] [5 1 2 3]]

8.3.40 arr-join

form code live
(k/arr-join ["1" "2" "3" "4"] " ") k.arr_join({'1','2','3','4'},' ') "1 2 3 4"

8.3.41 arr-interpose

form code live
(k/arr-interpose ["1" "2" "3" "4"] "XX") k.arr_interpose({'1','2','3','4'},'XX') ["1" "XX" "2" "XX" "3" "XX" "4"]

8.3.42 arr-repeat

form code live
[(k/arr-repeat "1" 4) (k/arr-repeat (k/inc-fn -1) 4)] {k.arr_repeat('1',4),k.arr_repeat(k.inc_fn(-1),4)} [["1" "1" "1" "1"] [0 1 2 3]]

8.3.43 arr-random

form code live
(k/arr-random [1 2 3 4]) k.arr_random({1,2,3,4}) 3

8.3.44 arr-normalise

form code live
(k/arr-normalise [1 2 3 4]) k.arr_normalise({1,2,3,4}) [0.1 0.2 0.3 0.4]

8.3.45 arr-sample

form code live
(k/arr-sample ["left" "right" "up" "down"] [0.1 0.2 0.3 0.4]) k.arr_sample({'left','right','up','down'},{0.1,0.2,0.3,0.4}) "down"

8.3.46 arrayify

form code live
[(k/arrayify 1) (k/arrayify [1])] {k.arrayify(1),k.arrayify({1})} [[1] [1]]

8.4 Base Lib - Object

8.4.1 obj-empty?

form code live
[(k/obj-empty? {}) (k/obj-empty? {:a 1})] {k.obj_emptyp({}),k.obj_emptyp({a=1})} [true false]

8.4.2 obj-not-empty?

form code live
[(k/obj-not-empty? {}) (k/obj-not-empty? {:a 1})] {k.obj_not_emptyp({}),k.obj_not_emptyp({a=1})} [false true]

8.4.3 obj-first-key

form code live
(k/obj-first-key {:a 1}) k.obj_first_key({a=1}) "a"

8.4.4 obj-first-val

form code live
(k/obj-first-val {:a 1}) k.obj_first_val({a=1}) 1

8.4.5 obj-keys

form code live
(k/obj-keys {:a 1, :b 2}) k.obj_keys({a=1,b=2}) ["a" "b"]

8.4.6 obj-vals

form code live
(k/obj-vals {:a 1, :b 2}) k.obj_vals({a=1,b=2}) [1 2]

8.4.7 obj-pairs

form code live
(k/obj-pairs {:a 1, :b 2, :c 2}) k.obj_pairs({a=1,b=2,c=2}) [["a" 1] ["b" 2] ["c" 2]]

8.4.8 obj-clone

form code live
(k/obj-clone {:a 1, :b 2, :c 3}) k.obj_clone({a=1,b=2,c=3}) {"a" 1, "b" 2, "c" 3}

8.4.9 obj-assign

form code live
(do (var out := {:a 1}) (k/obj-assign out {:b 2, :c 3}) out) local out = {a=1} k.obj_assign(out,{b=2,c=3}) out {"a" 1, "b" 2, "c" 3}

8.4.10 obj-assign-nested

form code live
[(k/obj-assign-nested {:a 1} {:b 2}) (k/obj-assign-nested {:a {:b {:c 1}}} {:a {:b {:d 1}}})] { k.obj_assign_nested({a=1},{b=2}), k.obj_assign_nested({a={b={c=1}}},{a={b={d=1}}}) } [{"a" 1, "b" 2} {"a" {"b" {"d" 1, "c" 1}}}]

8.4.11 obj-assign-with

form code live
(k/obj-assign-with {:a {:b true}} {:a {:c true}} k/obj-assign) k.obj_assign_with({a={b=true}},{a={c=true}},k.obj_assign) {"a" {"b" true, "c" true}}

8.4.12 obj-from-pairs

form code live
(k/obj-from-pairs [["a" 1] ["b" 2] ["c" 3]]) k.obj_from_pairs({{'a',1},{'b',2},{'c',3}}) {"a" 1, "b" 2, "c" 3}

8.4.13 obj-del

form code live
(k/obj-del {:a 1, :b 2, :c 3} ["a" "b"]) k.obj_del({a=1,b=2,c=3},{'a','b'}) {"c" 3}

8.4.14 obj-del-all

form code live
(k/obj-del-all {:a 1, :b 2, :c 3}) k.obj_del_all({a=1,b=2,c=3}) {}

8.4.15 obj-pick

form code live
(k/obj-pick {:a 1, :b 2, :c 3} ["a" "b"]) k.obj_pick({a=1,b=2,c=3},{'a','b'}) {"a" 1, "b" 2}

8.4.16 obj-omit

form code live
(k/obj-omit {:a 1, :b 2, :c 3} ["a" "b"]) k.obj_omit({a=1,b=2,c=3},{'a','b'}) {"c" 3}

8.4.17 obj-transpose

form code live
(k/obj-transpose {:a "x", :b "y", :c "z"}) k.obj_transpose({a='x',b='y',c='z'}) {"z" "c", "x" "a", "y" "b"}

8.4.18 obj-nest

form code live
(k/obj-nest ["a" "b"] 1) k.obj_nest({'a','b'},1) {"a" {"b" 1}}

8.4.19 obj-map

form code live
(k/obj-map {:a 1, :b 2, :c 3} k/inc) k.obj_map({a=1,b=2,c=3},function (x) return x + 1 end) {"a" 2, "b" 3, "c" 4}

8.4.20 obj-filter

form code live
(k/obj-filter {:a 1, :b 2, :c 3} k/odd?) k.obj_filter({a=1,b=2,c=3},function (x) return not (0 == (x % 2)) end) {"a" 1, "c" 3}

8.4.21 obj-keep

form code live
(k/obj-keep {:a 1, :b 2, :c 3} (fn:> [x] (:? (k/odd? x) x))) k.obj_keep({a=1,b=2,c=3},function (x) return not (0 == (x % 2)) and x or nil end) {"a" 1, "c" 3}

8.4.22 obj-keepf

form code live
(k/obj-keepf {:a 1, :b 2, :c 3} k/odd? k/identity) k.obj_keepf({a=1,b=2,c=3},function (x) return not (0 == (x % 2)) end,k.identity) {"a" 1, "c" 3}

8.4.23 obj-intersection

form code live
(k/obj-intersection {:a true, :b true} {:c true, :b true}) k.obj_intersection({a=true,b=true},{c=true,b=true}) ["b"]

8.4.24 obj-difference

form code live
[(k/obj-difference {:a true, :b true} {:c true, :b true}) (k/obj-difference {:c true, :b true} {:a true, :b true})] { k.obj_difference({a=true,b=true},{c=true,b=true}), k.obj_difference({c=true,b=true},{a=true,b=true}) } [["c"] ["a"]]

8.4.25 obj-keys-nested

form code live
(k/obj-keys-nested {:a {:b {:c 1, :d 2}, :e {:f 4, :g 5}}} []) k.obj_keys_nested({a={b={c=1,d=2},e={f=4,g=5}}},{}) [[["a" "e" "f"] 4] [["a" "e" "g"] 5] [["a" "b" "d"] 2] [["a" "b" "c"] 1]]

8.4.26 to-flat

form code live
[(k/to-flat {:a 1, :b 2, :c 3}) (k/to-flat (k/obj-pairs {:a 1, :b 2, :c 3}))] { k.to_flat({a=1,b=2,c=3}), k.to_flat(k.obj_pairs({a=1,b=2,c=3})) } [["a" 1 "b" 2 "c" 3] ["a" 1 "b" 2 "c" 3]]

8.4.27 from-flat

form code live
(k/from-flat ["a" 1 "b" 2 "c" 3] k/step-set-key {}) k.from_flat({'a',1,'b',2,'c',3},k.step_set_key,{}) {"a" 1, "b" 2, "c" 3}

8.4.28 get-in

form code live
(k/get-in {:a {:b {:c 1}}} ["a" "b"]) k.get_in({a={b={c=1}}},{'a','b'}) {"c" 1}

8.4.29 set-in

form code live
(do (var out {:a {:b {:c 1}}}) (k/set-in out ["a" "b"] 2) out) local out = {a={b={c=1}}} k.set_in(out,{'a','b'},2) out {"a" {"b" 2}}

8.4.30 eq-nested

form code live
[(k/eq-nested {:a {:b {:c 1}}} {:a {:b {:c 1}}}) (k/eq-nested {:a {:b {:c 1}}} {:a {:b {:c 2}}}) (k/eq-nested 1 1) (k/eq-nested 1 2) (k/eq-nested [1] [1]) (k/eq-nested [1] [2]) (k/eq-nested {:a [{:b {:c 1}}]} {:a [{:b {:c 1}}]}) (k/eq-nested {:a [{:b {:c 1}}]} {:a [{:b {:c 2}}]})] { k.eq_nested({a={b={c=1}}},{a={b={c=1}}}), k.eq_nested({a={b={c=1}}},{a={b={c=2}}}), k.eq_nested(1,1), k.eq_nested(1,2), k.eq_nested({1},{1}), k.eq_nested({1},{2}), k.eq_nested({a={{b={c=1}}}},{a={{b={c=1}}}}), k.eq_nested({a={{b={c=1}}}},{a={{b={c=2}}}}) } [true false true false true false true false]

8.4.31 obj-diff

form code live
(k/obj-diff {:a 1, :b 2} {:a 1, :c 2}) k.obj_diff({a=1,b=2},{a=1,c=2}) {"c" 2}

8.4.32 obj-diff-nested

form code live
[(k/obj-diff-nested {:a 1, :b 2} {:a 1, :c 2}) (k/obj-diff-nested {:a 1, :b {:c 3}} {:a 1, :b {:d 3}}) (k/obj-diff-nested {:a 1, :b {:c {:d 3}}} {:a 1, :b {:c {:e 3}}})] { k.obj_diff_nested({a=1,b=2},{a=1,c=2}), k.obj_diff_nested({a=1,b={c=3}},{a=1,b={d=3}}), k.obj_diff_nested({a=1,b={c={d=3}}},{a=1,b={c={e=3}}}) } [{"c" 2} {"b" {"d" 3}} {"b" {"c" {"e" 3}}}]

8.4.33 objify

decodes object if string

form code live
(k/objify "{}") k.objify('{}') {}

8.4.34 clone-nested

form code live
(k/clone-nested {:a [1 2 3 {:b [4 5 6]}]}) k.clone_nested({a={1,2,3,{b={4,5,6}}}}) {"a" [1 2 3 {"b" [4 5 6]}]}

8.4.35 walk

form code live
(k/walk [1 {:a {:b 3}}] (fn [x] (return (:? (k/is-number? x) (+ x 1) x))) k/identity) k.walk({1,{a={b=3}}},function (x) return ('number' == type(x)) and (x + 1) or x end,k.identity) [2 {"a" {"b" 4}}]

8.4.36 get-data

form code live
(k/get-data {:a 1, :b "hello", :c {:d [1 2 (fn:>)], :e "hello", :f {:g (fn:>), :h 2}}}) k.get_data({ a=1, b='hello', c={ d={ 1, 2, function () return nil end }, e='hello', f={ g=function () return nil end, h=2 } } }) {"a" 1, "b" "hello", "c" {"d" [1 2 "<function>"], "f" {"g" "<function>", "h" 2}, "e" "hello"}}

8.4.37 get-spec

form code live
(k/get-spec {:a 1, :b "hello", :c {:d [1 2 (fn:>)], :e "hello", :f {:g (fn:>), :h 2}}}) k.get_spec({ a=1, b='hello', c={ d={ 1, 2, function () return nil end }, e='hello', f={ g=function () return nil end, h=2 } } }) {"a" "number", "b" "string", "c" {"d" ["number" "number" "function"], "f" {"g" "function", "h" "number"}, "e" "string"}}

9 Iter Lib

9.0.1 for:iter

form code live
(do (var out []) (for:iter [e (it/iter-from-arr [1 2 3 4])] (x:arr-push out e)) out) local out = {} for e in coroutine.wrap(function () for _, v in ipairs({1,2,3,4}) do coroutine.yield(v) end end) do table.insert(out,e) end out [1 2 3 4]

9.0.2 iter

form code live
(it/iter [1 2 3 4 5]) it.iter({1,2,3,4,5}) function: builtin#37

9.0.3 iter?

form code live
(it/iter? (it/iter [])) it.iterp(it.iter({})) true

9.0.4 iter-next

form code live
(it/iter-next (it/iter [1 2 3])) it.iter({1,2,3})() 1

9.0.5 iter-has?

form code live
[(it/iter-has? 123) (it/iter-has? [1 2 3])] { ('table' == type(123)) and ('function' == (123)['iterator']), ('table' == type({1,2,3})) and ('function' == ({1,2,3})['iterator']) } [false false]

9.0.6 iter-native?

form code live
[(it/iter-native? (it/iter [1 2 3])) (it/iter-native? 1)] {'function' == type(it.iter({1,2,3})),'function' == type(1)} [true false]

9.0.7 iter-eq

form code live
(do (var eq-fn (fn:> [a b] (== a b))) [(it/iter-eq (it/iter [1 2 4 4]) (it/iter [1 2 4 4]) eq-fn) (it/iter-eq (it/iter [1 2 4 4]) (it/iter [1 2 3 4]) eq-fn) (it/iter-eq (it/iter [1 2 4]) (it/iter [1 2 4 4]) eq-fn) (it/iter-eq (it/iter [1 2 4 4]) (it/iter [1 2 4]) eq-fn)]) local function eq_fn(a,b) return a == b end { it.iter_eq(it.iter({1,2,4,4}),it.iter({1,2,4,4}),eq_fn), it.iter_eq(it.iter({1,2,4,4}),it.iter({1,2,3,4}),eq_fn), it.iter_eq(it.iter({1,2,4}),it.iter({1,2,4,4}),eq_fn), it.iter_eq(it.iter({1,2,4,4}),it.iter({1,2,4}),eq_fn) } [true false false false]

9.0.8 iter-null

form code live
(it/arr< (it/iter-null)) it.arr_lt(it.iter_null()) {}

9.0.9 collect

form code live
(it/collect [1 2 3 4] k/step-push []) it.collect(it.iter({1,2,3,4}),k.step_push,{}) [1 2 3 4]

9.0.10 nil<

form code live
(it/nil< (it/iter [1 2 3 4])) it.nil_lt(it.iter({1,2,3,4})) nil

9.0.11 arr<

form code live
(it/arr< (it/iter [1 2 3 4])) it.arr_lt(it.iter({1,2,3,4})) [1 2 3 4]

9.0.12 obj<

form code live
(it/obj< (it/iter [["a" 2] ["b" 4]])) it.obj_lt(it.iter({{'a',2},{'b',4}})) {"a" 2, "b" 4}

9.0.13 take

form code live
(it/arr< (it/take 4 (it/iter [1 2 3 4 5 6 7]))) it.arr_lt(it.take(4,it.iter({1,2,3,4,5,6,7}))) [1 2 3 4]

9.0.14 constantly

form code live
(it/arr< (it/take 4 (it/constantly 1))) it.arr_lt(it.take(4,it.constantly(1))) [1 1 1 1]

9.0.15 iterate

form code live
(it/arr< (it/take 4 (it/iterate k/inc 11))) it.arr_lt(it.take(4,it.iterate(function (x) return x + 1 end,11))) [11 12 13 14]

9.0.16 repeatedly

form code live
(it/arr< (it/take 5 (it/repeatedly (fn [] (return 5))))) it.arr_lt(it.take(5,it.repeatedly(function () return 5 end))) [5 5 5 5 5]

9.0.17 cycle

form code live
(it/arr< (it/take 5 (it/cycle [1 2 3]))) it.arr_lt(it.take(5,it.cycle({1,2,3}))) [1 2 3 1 2]

9.0.18 range

form code live
(it/arr< (it/range [-10 -3])) it.arr_lt(it.range({-10,-3})) [-10 -9 -8 -7 -6 -5 -4]

9.0.19 drop

form code live
(it/arr< (it/drop 3 (it/range 10))) it.arr_lt(it.drop(3,it.range(10))) [3 4 5 6 7 8 9]

9.0.20 peek

form code live
(do (var out := []) (it/nil< (it/peek (fn [e] (k/step-push out e)) [1 2 3 4 5])) out) local out = {} it.nil_lt(it.peek(function (e) k.step_push(out,e) end,{1,2,3,4,5})) out [1 2 3 4 5]

9.0.21 map

form code live
(it/arr< (it/map k/inc [1 2 3])) it.arr_lt(it.map(function (x) return x + 1 end,{1,2,3})) [2 3 4]

9.0.22 mapcat

form code live
[(it/arr< (it/mapcat (fn:> [x] [x x]) [1 2 3])) (it/arr< (it/mapcat (fn:> [x] x) [[1 2 3] [4 5 6]])) (it/arr< (it/mapcat (fn:> [x] (it/range x)) (it/range 4))) (it/arr< (it/mapcat (fn:> [x] x) [(it/range 3) (it/range 3)]))] { it.arr_lt(it.mapcat(function (x) return {x,x} end,{1,2,3})), it.arr_lt(it.mapcat(function (x) return x end,{{1,2,3},{4,5,6}})), it.arr_lt(it.mapcat(function (x) return it.range(x) end,it.range(4))), it.arr_lt(it.mapcat(function (x) return x end,{it.range(3),it.range(3)})) } [[1 1 2 2 3 3] [1 2 3 4 5 6] [0 0 1 0 1 2] [0 1 2 0 1 2]]

9.0.23 concat

form code live
(it/arr< (it/concat [(it/range 3) (it/range [4 6])])) it.arr_lt(it.concat({it.range(3),it.range({4,6})})) [0 1 2 4 5]

9.0.24 filter

form code live
(it/arr< (it/filter k/odd? [1 2 3 4])) it.arr_lt(it.filter(function (x) return not (0 == (x % 2)) end,{1,2,3,4})) [1 3]

9.0.25 keep

form code live
(it/arr< (it/keep (fn:> [x] (:? (k/odd? x) {:a x})) [1 2 3 4])) it.arr_lt(it.keep(function (x) return not (0 == (x % 2)) and {a=x} or nil end,{1,2,3,4})) [{"a" 1} {"a" 3}]

9.0.26 partition

form code live
(it/arr< (it/partition 3 (it/range 10))) it.arr_lt(it.partition(3,it.range(10))) [[0 1 2] [4 5 6] [8 9]]

9.0.27 take-nth

form code live
[(it/arr< (it/take-nth 2 (it/range 10))) (it/arr< (it/take-nth 3 (it/range 10))) (it/arr< (it/take-nth 4 (it/drop 1 (it/range 10))))] { it.arr_lt(it.take_nth(2,it.range(10))), it.arr_lt(it.take_nth(3,it.range(10))), it.arr_lt(it.take_nth(4,it.drop(1,it.range(10)))) } [[0 2 4 6 8] [0 3 6 9] [1 5 9]]
source: notebooks/stdlang_book/walkthrough_lua.clj