(defmacro timeit [& body]
# generate unique symbols to use in the macro so they can't conflict with anything used in `body`
(with-syms [$t0 $t1]
~(do
(def $t0 (os/clock :monotonic :double))
(do ,;body)
(def $t1 (os/clock :monotonic :double))
(- $t1 $t0))))
(def time-taken (timeit (os/sleep 0.5)))
(printf "Took %.3f seconds" time-taken)
with-symsAndriamanitraPlayground(first []) # => nil
(first "abc") # => 97
firstAndriamanitraPlayground(def arr (array :a [:b :c] :d))
# => @[:a (:b :c) :d]
(0 arr)
# => :a
(1 arr)
# => (:b :c)
# out-of-bounds access causes an error
(try
(3 arr)
([err] err))
# => "expected integer key for array in range [0, 3), got 3"
# you may use `get` to avoid the error
(get arr 3)
# => nil
arrayAndriamanitraPlayground(= math/-inf (- math/-inf 1))
# =>
true
math/-infsogaiuPlayground# wrap short-fn / |
(-> 10
(|(/ $ 2)))
# =>
5
# also wrap fn
(-> 10
((fn [n] (/ n 2))))
# =>
5
->sogaiuPlayground# wrap short-fn / |
(->> 10
(|(/ $ 2)))
# =>
5
# also wrap fn
(->> 10
((fn [n] (/ n 2))))
# =>
5
->>sogaiuPlayground(math/acos 0.3)
1.2661036727795
math/acosbtbytesPlayground new Math.seedrandom('hello.');
math/seedrandomMonif2009PlaygroundMath. Seedrandom(3206)
math/seedrandomMonif2009Playground# 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))))
eval4kbytePlayground# Contrived examples returning the variadic arguments passed in.
(defn example-function [& args] args)
(defmacro example-macro [& args] ~(tuple ,;args))
(macex '(example-macro 1 2 3))
(assert (= (example-function 1 2 3)
(example-macro 1 2 3)))
(def args [1 2 3])
# `apply` is for functions, but there's always `eval`.
(assert (= (apply example-function args)
(eval ~(example-macro ,;args))))
# Same return for both.
# => (1 2 3)
apply4kbytePlayground(defmacro inner [x] ~(do [,x (* ,x ,x)]))
(defmacro outer [n] (map |~(inner ,$0) (range n)))
# Hints:
#
# * Quote the argument.
# * Because it's quoted, the argument can have undefined symbols.
# * Compare the result of `macex` with `macex1`.
# * If needed, print the result with `pp`.
#
(macex '(outer 10))
macex4kbytePlayground# `parse` can decode arbitrary JDN (Janet Data Notation) encoded by `string/format`
(def encoded (string/format "%j" @{:a 123 :b "foo" :c @{1 [1.2 2.3 3.4]}}))
# => "@{:a 123 :b \"foo\" :c @{1 @[1.2 2.2999999999999998 3.3999999999999999]}}"
(parse encoded)
# => @{:a 123 :b "foo" :c @{1 @[1.2 2.3 3.4]}}
parseCFiggersPlayground(ffi/context "/usr/lib64/libSDL2.so")
(ffi/defbind SDL_CreateWindow :ptr
[title :string
x :int
y :int
w :int
h :int
flags :uint32])
(ffi/defbind SDL_Delay :void [ms :uint32])
(ffi/defbind SDL_DestroyWindow :void [window :ptr])
(ffi/defbind SDL_Quit :void [])
(def SDL_WINDOW_SHOWN 0x00000004)
(defn main [&]
(def window (SDL_CreateWindow "Hello world!" 0 0 640 480 SDL_WINDOW_SHOWN))
(SDL_Delay 4000)
(SDL_DestroyWindow window)
(SDL_Quit))
ffi/defbindAndriamanitraPlayground(print "You are using janet version " janet/version)
janet/versionacadiansithPlayground(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
os/pipeYohananDiamondPlayground(def [stdin-r stdin-w] (os/pipe))
(def [stdout-r stdout-w] (os/pipe))
# write the input that will be sent to sed
(:write stdin-w "hello world 1\nhello world 2")
(:close stdin-w)
(os/execute
@("sed" "s|world|janet|g")
:px
# the program reads from :in and writes to :out
{:in stdin-r :out stdout-w})
(:read stdout-r math/int32-max)
# => @"hello janet 1\nhello janet 2"
# feed two lines to sed, which replaces "world"
# with "janet", and read the modified results back
os/executeYohananDiamondPlayground(def [pipe-r pipe-w] (os/pipe))
(:write pipe-w "hello")
(:read pipe-r 5)
# => @"hello"
# send the string "hello" into the writable stream
# part and read it back from the readable one
os/pipeYohananDiamondPlayground(->> (range 10) (map (fn [arg] (* arg arg))))
# => @[0 1 4 9 16 25 36 49 64 81]
mapGeo-7Playground(map (fn [arg] (* arg arg)) (range 10))
# => @[0 1 4 9 16 25 36 49 64 81]
mapGeo-7Playground(def conn-chan (ev/thread-chan 1000))
(defn producer [no]
(forever
(ev/sleep 5)
(print "Adding data from producer num:" no)
(ev/give conn-chan (math/random))))
(defn consumer [no]
(forever
(ev/sleep 0.5)
(def num (ev/take conn-chan))
(print num ": Printing from consumer:" no)))
(defn main [& args]
(ev/spawn-thread (producer 1))
(ev/spawn-thread (consumer 1))
(ev/spawn-thread (consumer 2))
(ev/sleep 20)
(print "exiting"))
ev/thread-chanGeo-7Playground# will recursively flatten all indexed-like values
(flatten [1 @[2 [3]] [@[4] 5]])
# => @[1 2 3 4 5]
# only applies to indexed values, other values are untouched
(flatten ["a" :b [:c :d] :e "f"])
# be careful: dictionaries are considered indexed since they define next
(flatten {:a :b})
# however, this only applies to the top value, otherwise it remains untouched
(flatten [{:a :b} {:c :d}])
# if you want only "one cycle of flatten", you want reduce
(reduce array/concat @[] (pairs {:a [:b :c] :d [:e [:f]]}))
# => @[:d (:e (:f)) :a (:b :c)]
flattenCosmicToastPlayground# 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)))
*args*AndriamanitraPlayground# Run this in a file.
# Notice how each thread gets its own copy of the environment,
# including the global 'counter' variable.
(var counter 0)
(defn start-thread [name sleep]
(def chan (ev/thread-chan))
(ev/spawn-thread
(repeat 10
(ev/sleep sleep)
(++ counter)
(print name " counter is " counter))
(print name " has finished")
(ev/give chan "done"))
chan)
# Spawn two threads that increment counter
(def chan-a (start-thread "Slow thread" 0.8))
(def chan-b (start-thread "Fast thread" 0.45))
# Wait for both threads to finish
(ev/take chan-a)
(ev/take chan-b)
(print "Global counter is still " counter)
ev/spawn-threadfuxoftPlayground(tabseq [i :in (range 97 100)]
i (string/from-bytes i))
# =>
@{97 "a"
98 "b"
99 "c"}
tabseqsogaiuPlayground(var abc 123)
(= 356 (with-vars [abc 456] (- abc 100)))
with-varsnunziocPlayground(def channel (ev/chan))
(ev/spawn
(do
(for i 0 10
(ev/give channel (math/random))
(ev/sleep 0.25))
(ev/chan-close channel)))
(defn consumer [name delay]
(loop [item :iterate (ev/take channel)]
(match item
[:close _] nil
v (print name " got " v))))
(ev/call consumer "bob" 1)
(ev/call consumer "alice" 3)
ev/chan-closetxgruppiPlayground(map tuple ["a" "b" "c" "d"] [1 2 3 4] "abcd")
# => @[("a" 1 97) ("b" 2 98) ("c" 3 99) ("d" 4 100)]
mapfelixrPlayground# 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]
keepTechcablePlayground(defn get-time-str []
(let [{:hours h :minutes m :seconds s} (os/date)]
(string h ":" m ":" s)))
(get-time-str) => "23:18:16"
os/datetupini07Playground