Janet
A dynamic language and bytecode vm
Install / Use
/learn @janet-lang/JanetREADME
Janet is a programming language for system scripting, expressive automation, and extending programs written in C or C++ with user scripting capabilities.
Janet makes a good system scripting language, or a language to embed in other programs. It's like Lua and GNU Guile in that regard. It has more built-in functionality and a richer core language than Lua, but smaller than GNU Guile or Python. However, it is much easier to embed and port than Python or Guile.
There is a REPL for trying out the language, as well as the ability to run script files. This client program is separate from the core runtime, so Janet can be embedded in other programs. Try Janet in your browser at https://janet-lang.org.
<br>Examples
See the examples directory for all provided example programs.
Game of Life
# John Conway's Game of Life
(def- window
(seq [x :range [-1 2]
y :range [-1 2]
:when (not (and (zero? x) (zero? y)))]
[x y]))
(defn- neighbors
[[x y]]
(map (fn [[x1 y1]] [(+ x x1) (+ y y1)]) window))
(defn tick
"Get the next state in the Game Of Life."
[state]
(def cell-set (frequencies state))
(def neighbor-set (frequencies (mapcat neighbors state)))
(seq [coord :keys neighbor-set
:let [count (get neighbor-set coord)]
:when (or (= count 3) (and (get cell-set coord) (= count 2)))]
coord))
(defn draw
"Draw cells in the game of life from (x1, y1) to (x2, y2)"
[state x1 y1 x2 y2]
(def cellset @{})
(each cell state (put cellset cell true))
(loop [x :range [x1 (+ 1 x2)]
:after (print)
y :range [y1 (+ 1 y2)]]
(file/write stdout (if (get cellset [x y]) "X " ". ")))
(print))
# Print the first 20 generations of a glider
(var *state* '[(0 0) (-1 0) (1 0) (1 1) (0 2)])
(for i 0 20
(print "generation " i)
(draw *state* -7 -7 7 7)
(set *state* (tick *state*)))
TCP Echo Server
# A simple TCP echo server using the built-in socket networking and event loop.
(defn handler
"Simple handler for connections."
[stream]
(defer (:close stream)
(def id (gensym))
(def b @"")
(print "Connection " id "!")
(while (:read stream 1024 b)
(printf " %v -> %v" id b)
(:write stream b)
(buffer/clear b))
(printf "Done %v!" id)
(ev/sleep 0.5)))
(net/server "127.0.0.1" "8000" handler)
Windows FFI Hello, World!
# Use the FFI to popup a Windows message box - no C required
(ffi/context "user32.dll")
(ffi/defbind MessageBoxA :int
[w :ptr text :string cap :string typ :int])
(MessageBoxA nil "Hello, World!" "Test" 0)
Language Features
- 600+ functions and macros in the core library
- Built-in socket networking, threading, subprocesses, and file system functions.
- Parsing Expression Grammars (PEG) engine as a more robust Regex alternative
- Macros and compile-time computation
- Per-thread event loop for efficient IO (epoll/IOCP/kqueue)
- First-class green threads (continuations) as well as OS threads
- Erlang-style supervision trees that integrate with the event loop
- First-class closures
- Garbage collection
- Distributed as janet.c and janet.h for embedding into a larger program.
- Python-style generators (implemented as a plain macro)
- Mutable and immutable arrays (array/tuple)
- Mutable and immutable hashtables (table/struct)
- Mutable and immutable strings (buffer/string)
- Tail recursion
- Interface with C functions and dynamically load plugins ("natives").
- Built-in C FFI for when the native bindings are too much work
- REPL development with debugger and inspectable runtime
Documentation
- For a quick tutorial, see the introduction for more details.
- For the full API for all functions in the core library, see the core API doc.
Documentation is also available locally in the REPL.
Use the (doc symbol-name) macro to get API
documentation for symbols in the core library. For example,
(doc apply)
shows documentation for the apply function.
To get a list of all bindings in the default
environment, use the (all-bindings) function. You
can also use the (doc) macro with no arguments if you are in the REPL
to show bound symbols.
Source
You can get the source on GitHub or SourceHut. While the GitHub repo is the official repo, the SourceHut mirror is actively maintained.
Spork and JPM
Spork and JPM are two companion projects to Janet. They are optional, especially in an embedding use case.
Spork is a collection of common utility modules, and several packaged scripts
like janet-format for code formatting, janet-netrepl for a socket-based
REPL, and janet-pm for a comprehensive Janet project manager tool. The
modules in spork are less stable than the interfaces in core Janet, although
we try to prevent breaking changes to existing modules, with a preference to
add new modules and functions. Spork requires a C compiler to build and install
various extenstion components such as miniz and JSON utilities. Many spork
sub-modules, for example spork/path, are independent and can be manually
vendored in programmer projects without fully installing spork.
When install Spork, scripts will be installed to $JANET_PATH/bin/ on POSIX systems by default. This likely needs to be added to the path to use these scripts.
JPM is the older, more opinionated, project manager tool, which has it's pros and cons. It does not require a C compiler to build and install, but is less flexible and is not receiving many changes and improvements going forward. It may also be harder to configure correctly on new systems. In that sense, it may be more stable.
JPM will install to /usr/local/bin/ on posix systems by default, which may or may not be on your PATH.
Building
When building from source, for stability, please use the latest tagged release. For
example, run git checkout $(git describe --tags --abbrev=0) after cloning but
before building. For the latest development, build directly on the master
branch. The master branch is not-necessarily stable as most Janet development
happens directly on the master branch.
macOS and Unix-like
The Makefile is non-portable and requires GNU-flavored make.
cd somewhere/my/projects/janet
make
make test
make repl
make install
make install-spork-git # optional
make install-jpm-git # optional
Find out more about the available make targets by running make help.
Alpine Linux
To build a statically-linked build of Janet, Alpine Linux + MUSL is a good combination. Janet can also be built inside a docker container or similar in this manner. This is a great way to try Janet without committing to a full install or needing to customize the default install.
docker run -it --rm alpine /bin/ash
$ apk add make gcc musl-dev git
$ git clone https://github.com/janet-lang/janet.git
$ cd janet
$ make -j10
$ make test
$ make install
$ make install-spork-git # optional
$ make install-jpm-git # optional
Note that for a true statically-linked binary with MUSL, one needs to add -static to the Makefile flags. This
will also disable runtime loading of native modules (plugins) as well as the FFI.
32-bit Haiku
32-bit Haiku build instructions are the same as the UNIX-like build instructions,
but you need to specify an alternative compiler, such as gcc-x86.
cd somewhere/my/projects/janet
make CC=gcc-x86
make test
make repl
make install
make install-spork-git # optional
make install-jpm-git # optional
FreeBSD
FreeBSD build instructions are the same as the UNIX-like build instructions,
but you need gmake to compile. Alternatively, install the package directly with pkg install lang/janet.
cd somewhere/my/projects/janet
gmake
gmake test
gmake repl
gmake install
gmake install-spork-git # optional
gmake install-jpm-git # optional
NetBSD
NetBSD build instructions are the same as the FreeBSD build instructions.
Alternatively, install the package directly with pkgin install janet.
illumos
Building on illumos is exactly the same as building on FreeBSD.
Windows
- Install Visual Studio or Visual Studio Build Tools.
- Run a Visual Studio Command Prompt (
cl.exeandlink.exeneed to be on your PATH) andcdto the directory with Janet. - Run
build_winto compile Janet. - Run
build_win testto make sure everything is working.
To build an .msi installer executable, in addition to the above steps, you will have to:
- Install, or otherwise add to your PATH the WiX 3.14 Toolset.
- Run
build_win dist.
Now you should have an .msi. You can run build_win install to install the .msi, or execute the file itself.
Meson
Janet also has a build file for Meson, a cross-platform build system. Although Meson has a Python dependency, Meson is a very complete build system that is maybe mor
Related Skills
node-connect
346.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
107.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
346.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
346.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
