- Take advantage of short functions. For example, something like
(some-function(def a val)a)can be(|(some-function $ $)val). They can be nested too! - Recursive functions are often shorter than mutable variables.
(defn f[a]...)(f a)=>((fn f[a]...)a)
- Use
ppinstead ofprintfor numbers and quotes - Often you can use a symbol or keyword instead of a string, e.g.
"Fizz"=>'Fizzor:Fizz. Using'Fizzalso means it will work withpp. Symbols and keywords can also be treated as sequences for use withmapand similar functions.:by itself is a valid keyword and is 1 byte shorter than the empty string,"".
- Read the docs. There are a lot of useful functions in there.
- A lot of functions take variadic arguments, especially math ones. So you can reuse them, such as
(-= i(* 2 x))=>(-= i x x)or(<(pp i)x y) - Splice is useful, e.g.
sum=>+;, or you can dostring;to join a list,print;, etc.- Note that
sumdoes work on strings, which can't be spliced
- Note that
Looping over arguments
(reduce2|[(f $1)(g $1)](dyn :args))
(map|[(f $)(g $)](drop 1(dyn :args)))
(each a(drop 1(dyn :args))(f a)(g a))
each is good when you have multiple statements and/or nested functions, otherwise map/reduce2 is better. reduce2 avoids the first argument, but is slightly longer and you have to use $1 instead $ which evens up after 4 uses.
Indexing
There's a few different ways to get a value from a data structure such as a tuple:
(ds idx) # Shortest, but no default and errors when out of range
(idx ds) # The same but with different execution order I guess
(in ds idx default?) # Has default, still throws error when out of range, so only good for dictionaries
(get ds idx default?) # Nil/default when out of range
Related, you can use put on arrays/buffers and it will extend it and fill the empty spaces with nils/null bytes.
Conditionals
(if(cond)x y) # Short circuits, you can leave the false section out to return nil, needs a truthy or (falsey/nil) condition
(and/or cond x) # Short circuits, multiple conditions
(case n v x default) # Short circuits, checks specific values, has default
(in{v x}n default) # Same as case, but no short circuit
({v x n default}n) # Same again, but with more whitespace to save though using n twice
([x y]n) # Needs a numeric 0/1 condition
PEGs
Parsing Expression Grammars may, at first glance, seem too verbose to be useful in code golf. However they can usually be short enough to serve a similar purpose to regular expressions in other languages.
Basic Tips
peg/find[-all]andpeg/replace[-all]have shorter names than theirstring/-prefixed counterparts, and can always be used instead, even if you're not using more advanced PEG constructs.- To backtrack, you need to use
+(choice). All other constructs are greedy. - Remember that Janet is a Lisp, and PEGs may be built dynamically.
Examples
Parsing a date:
(def[y m d](peg/match'(5(+(number :d+)1))"2025-09-26"))