Basic tips
nil -> ()
(if(not a)b) -> (or a b) (if the return is not needed)
- Replace conditional blocks
{} with and or or chains if the return values allow it
- Spacing in ArkScript is much more flexible than in other Lisp-likes. For instance, a number can precede an identifier without a space, and lists don't need spaces around them.
(if(list:contains? lst val)...) -> (or(<(list:find lst val)0)...)
- Newlines can appear literally in strings
- Use a function call to replace multiple independent
let declarations
nil, 0, and empty containers are falsy
Importing
- Always use glob imports:
(import std.List) ... list:map -> (import std.List:*) ... map.
- Note the VM builtins and C++ builtins:
(import std.Sys:*) ... sys:args -> builtin__sys:args.
- If using functions from many files, try
(import std.Prelude), which provides all standard library files, but cannot be globbed.
- The standard library is big, with many useful functions (e.g.
list:permutations, math:prime?, ...).
std.Range is almost never necessary; use list:map and list:iota.
- Complex numbers require
math:complex- functions, which are expensive; simply implement them yourself using pairs of numbers.
Sequences
For sequence holes, recursion can often be used to avoid imports altogether. Additionally, you can often terminate via error to save bytes. For instance, compare the following ways to print the first 50 perfect squares:
(import std.List:*)(map(iota 1 50)(fun(n)(print(* n n)))) # 57 bytes, has import overhead
(let f(fun(n)(or(print(* n n))(< 49n)(f(+ 1n)))))(f 1) # 54 bytes, uses recursion
(let f(fun(n)(f(+(or(print(* n n))(< 49n)n)1))))(f 1) # 53 bytes, crashes because you can't add true to 1, saving a space
(mut n 0)(while(> 50n){(set n(+ 1n))(print(* n n))}) # 52 bytes, while loop still has potential sometimes