JanetDocsSourcePlaygroundTutorialsI'm Feeling luckyCommunityGitHub sign in

Community documentation for Janet

Supported Modules

Welcome, I'm happy to see you here! Feel free to pick a function and add a happy example, the more the merrier!

Loading...

Random Examples

(ev/spawn (os/sleep 1) (print "Hard work is done!"))

# prints "Hard work is done!" after one second
# this is the easiest way to put some forms on the event loop
# but do not forget REPL is blocking, for now, so run the example with `janet -e`
ev/spawnpepePlayground
(var abc 123)
(= 356 (with-vars [abc 456] (- abc 100)))
with-varsnunziocPlayground
(import spork/json)
(def input `` {"name": "person", "unknown": null, "happy": true, "sad": false} ``)

When calling, the json dictionary becomes a mutable table in janet.

(json/decode input)
@{"happy" true "name" "person" "sad" false "unknown" :null}

pass `true` as the first arg, and json keys become janet keywords.

(json/decode input true)
@{:happy true :name "person" :sad false :unknown :null}

pass `true` as the second arg, and json keys that map to `null` are not hydrated.

(json/decode input true true)
@{:happy true :name "person" :sad false}



spork/json/decodenickfunPlayground
# `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
(buffer/bit-set @"hahaha" 3) # => @"hahaha"

(buffer/bit-set @"what" 3) # => @"\x7Fhat"

buffer/bit-setjgartePlayground
# To make "stub functions" in an image, solving c interop problems like this:

# I hoped that I would be able to unmarshal the runtime.jimage, load my C functions,
# and Janet would use my app's functions instead of the stubs. However, during
# compilation, Janet seems to precompile all the top-level function calls. This
# means hotswapping the functions does nothing, and the Janet code continues to 
# use the stubs instead.
#
# I was hoping that there would be some way of telling Janet "don't precompile 
# this please", either a (defstubn ...) or the ability to do 
# (defn internal/redraw-ui [opts] (dyn)), where (dyn) is some abstract type that
# Janet can't precompute directly.
# https://github.com/janet-lang/janet/issues/1642


# pretend this is the stub function we want to replace
(defn greet [] (print "hello world"))

# make-image-dict determines which values will be filled in at
# "deserialization" time
(put make-image-dict greet 'greet)
(def pretend-env @{
  'some-function (fn [] (greet) (greet))})

(def compiled (make-image pretend-env))
# notice: the string "hello world" does not appear in the compiled result
(pp compiled)

# if we just try to (load-image compiled) at this point, it will raise,
# because we haven't specified what to do about 'greet

# we have to make an entry in the load-image-dict. note that
# it does not have to be the same value!
(put load-image-dict 'greet (fn [] (print "something else!")))

# now we can call load-image
(def pretend-env-reparsed (load-image compiled))

# and when we run this, we will see the replacement that we gave
((pretend-env-reparsed 'some-function))
make-image-dictveqqqPlayground
(string/join @["1" "2" "3"]) # => "123"
# The esp argument is optional, and defaults to empty string
string/joinyumaikasPlayground
(string/trimr " foo ")  # => " foo"
(string/trimr "_!_foo_!_" "_!")  # => "_!_foo"
string/trimrcellularmitosisPlayground
(each item [1 2 3 4] (print item))
# prints 1
# prints 2
# prints 3
# prints 4
# => nil
eachpepePlayground
# *doc-width* is bound to the keyword :doc-width - it can be used in place of
# :doc-width in a call to `dyn`, `setdyn`, or `with-dyns` and is preferable
# to using the keyword directly. When set to a number, it indicates the
# maximum width (in columns) of a row of text returned by `doc-format`.

# - Like *doc-color*, *doc-width* can be used to adjust the output of
#   `doc-format`.
# - When the :doc-width dynamic binding is not set, the default width is 80.
# - By default, `doc-format` adds 4 space indentation and subtracts 8 from
#   the value of the :doc-width dynamic binding to calculate a max width.

# Default:
# repl> (doc doc)
# 
# 
#     macro
#     boot.janet on line 3573, column 1
# 
#     (doc &opt sym)
# 
#     Shows documentation for the given symbol, or can show a list of 
#     available bindings. If sym is a symbol, will look for documentation 
#     for that symbol. If sym is a string or is not provided, will show 
#     all lexical and dynamic bindings in the current environment 
#     containing that string (all bindings will be shown if no string is 
#     given).

# With *doc-width*:
# repl> (with-dyns [*doc-width* 40] (doc doc))
# 
# 
#     macro
#     boot.janet on line 3573, column 1
# 
#     (doc &opt sym)
# 
#     Shows documentation for the 
#     given symbol, or can show a 
#     list of available bindings. 
#     If sym is a symbol, will 
#     look for documentation for 
#     that symbol. If sym is a 
#     string or is not provided, 
#     will show all lexical and 
#     dynamic bindings in the 
#     current environment 
#     containing that string (all 
#     bindings will be shown if 
#     no string is given).
*doc-width*quexxonPlayground
(string/find "needle"
             "hay hay hay needle hay")
# => 12
string/findsogaiuPlayground
(int/s64 42)    # => <core/s64 42>
(int/s64 42.1)  # => <core/s64 42>
(int/s64 "42")  # => <core/s64 42>
int/s64cellularmitosisPlayground
(defn bench `Feed bench a wrapped func and int, receive int for time in ns`
  [thunk times] 
  (def start (os/clock :cputime :tuple)) 
  (loop [_ :range [times]] 
    (thunk))
  (def end (os/clock :cputime :tuple)) 
  (/ (+ (* (- (end 0) (start 0)) 1e9) 
        (- (end 1) (start 1)))
     times))

# it turns out os/clock is pretty darn fast (comparatively)
(def iterations 2000000)
(bench |(os/clock :cputime :tuple) iterations) # 1283.30053 ns
(bench |(slurp "/proc/self/schedstat") iterations) # 7881.451760 ns
# these basically benchmark slurp
(bench |(do (def f (file/open "/proc/self/schedstat" :r))
            (def content (file/read f :all))
            (file/close f))
       iterations) # 4894.832760 ns
# even without opening and closing the file, reading in Janet's slower than os/clock
(def f (file/open "/proc/self/schedstat" :r)) 
(bench |(do (file/seek f :set 0)  
            (def content (file/read f :all))) iterations)  # 1802.511470 ns
(file/close f)

# Of course bench has some overhead, but it's amortized across iterations anyway
(bench (fn []) 10000000) # 42.030338 ns
os/clockveqqqPlayground

# sh/$'s contents are quasiquoted, allowing direct or string arguments
# so you need to unquote , variables:

(def out (file/open "trust-db.txt" :w))
(sh/$ "gpg" "--export-ownertrust" > ,out) # > requires an opened file object
(file/close out)

# note how > requires an opened file object
(with [out (file/open "trust-db.txt" :w)]
  (sh/$ gpg --export-ownertrust > ,out))
sh/$veqqqPlayground
(defn ddup [ds ks val]
  (update-in ds ks
    (fn [x]
      (if (= nil x)
        @[val]
        (array/push x val)))))

(var a @{})
(ddup a [:a] 1)
(ddup a [:a] 2)
(ddup a [:a] 3)
# @{:a @[1 2 3]}

update-insbjaverPlayground