Welcome, I'm happy to see you here! Feel free to pick a function and add a happy example, the more the merrier!
(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` (var abc 123 )
(= 356 (with-vars [abc 456 ] (- abc 100 )))(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 }
# `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]}} (buffer/bit-set @"hahaha" 3 ) # => @"hahaha"
(buffer/bit-set @"what" 3 ) # => @"\x7Fhat"
# 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 ))(string/join @["1" "2" "3" ]) # => "123"
# The esp argument is optional, and defaults to empty string (string/trimr " foo " ) # => " foo"
(string/trimr "_!_foo_!_" "_!" ) # => "_!_foo" (each item [1 2 3 4 ] (print item ))
# prints 1
# prints 2
# prints 3
# prints 4
# => nil # *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). (string/find "needle"
"hay hay hay needle hay" )
# => 12 (int/s64 42 ) # => <core/s64 42>
(int/s64 42.1 ) # => <core/s64 42>
(int/s64 "42" ) # => <core/s64 42>
(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
# 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 ))(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]}