Welcome, I'm happy to see you here! Feel free to pick a function and add a happy example, the more the merrier!
# absolute value of negatives, ignore positives
(keep |(if (< $ 0 ) (- $ ) nil ) [-1 2 -3 -4 -5 6 ]) # -> @[1 3 4 5]
# halves each even number, ignores odds
(keep |(when (even? $ ) (/ $ 2 )) [1 2 8 7 -2 ]) # -> @[1 4 -1]
(symbol "foo" ) # => foo
(def a "foo" )
(symbol a ) # => foo
(symbol a 42 nil ) # => foo42nil
# Walk from the API is defined using a case
(defn walk
`Iterate over the values in ast and apply f
to them. Collect the results in a data structure. If ast is not a
table, struct, array, or tuple,
returns form.`
[f form ]
(case (type form )
:table (walk-dict f form )
:struct (table/to-struct (walk-dict f form ))
:array (walk-ind f form )
:tuple (let [x (walk-ind f form )]
(if (= :parens (tuple/type form ))
(tuple/slice x )
(tuple/brackets ;x )))
form ))(map string/from-bytes "Hello, world!" ) # => @["H" "e" "l" "l" "o" "," " " "w" "o" "r" "l" "d" "!"] (- 1 )
# => -1 (table/to-struct @{:a 1 }) # => {:a 1} # Some tips for working with bytes and unicode:
(string/bytes "что-нибудь" ) #> (209 135 209 130 208 190 45 208 189 208 184 ...
(print (string/from-bytes 208 176 208 177 )) #> аб
(map string/from-bytes (string/bytes "что-нибудь" )) #> @["\xD1" "\x87" "\xD1" "\x82" "\xD0" "\xBE" ...
# Print renders "\xD1" "\x87" as ч, as unicode characters may have multiple bytes
# So use apply:
(apply print (map string/from-bytes
(string/bytes "что-нибудь" ))) #> что-нибудь # use (dyn :args) to get the value of dynamic binding *args*
(let [args (dyn :args )]
(if (= "-h" (get args 1 ))
(print "Usage: janet args.janet [-h] ARGS.." )
(printf "command line arguments:\n %q" args )))
(def [pipe-r pipe-w ] (os/pipe ))
(ev/spawn
# write to the pipe in a separate fiber
(for i 0 32000
(def str (string "Hello Janet " i "\n" ))
(:write pipe-w str ))
(:close pipe-w ))
(forever
(def text (:read pipe-r 4096 ))
(when (nil? text ) (break ))
(pp text ))
# read a series of strings from the pipe in parallel
# to writing to the other side, to avoid the program
# from hanging if the pipe is "full"
#
# see https://github.com/janet-lang/janet/issues/1265 (let [c (ev/chan 2 )]
(ev/give c :one )
(def first-check (ev/full c ))
(ev/give c :two )
(def second-check (ev/full c ))
(ev/take c )
(def third-check (ev/full c ))
[first-check second-check third-check ])
# => '(false true false)
# Linux pipes | send data through stdin
# To make linux programs accepting varied input forms:
(defn main [_ & args ]
# If no arguments, read from stdin
(let [data (if (empty? args ) (file/read stdin :all ) (string/join args " " ))]
(print (sum (flatten (parse-all data ))))))
# This accepts: 1 2 3 or "1" "2" "3" or "1 2 3" or "[1 2 3]" besides piping data in
# janet fib.janet 5 | janet sum.janet
# Allow file inputs also:
(defn main [_ & args ]
(let [data (cond (empty? args ) (file/read stdin :all )
(os/stat (first args )) (slurp (first args ))
(string/join args " " ))]
(print (sum (flatten (parse-all data ))))))(math/atan2 0 0 )
# => 0
# Contrived example returning the variadic arguments passed in.
(defmacro example-macro [& args ] ~(tuple ,;args ))
(example-macro 1 2 3 ) # => (1 2 3)
(def args [1 2 3 ])
# `apply` is for functions, but there's always `eval`.
(assert (= (example-macro 1 2 3 )
(eval ~(example-macro ,;args ))))(sort (keys default-peg-grammar ))
# => @[:A :D :H :S :W :a :a* :a+ :d :d* :d+ :h :h* :h+ :s :s* :s+ :w :w* :w+] (sort @[5 4 1 3 2 ]) # -> @[1 2 3 4 5]
(sort @[5 4 1 3 2 ] > ) # -> @[5 4 3 2 1]