{"slug": "kaappi-r7rs-scheme-written-in-zig", "title": "Kaappi – r7rs scheme written in Zig", "summary": "Kaappi, a complete R7RS-small Scheme implementation written in Zig, has been released with 641 built-in procedures, 32 syntax forms, 14 standard libraries, 171 SRFIs, a C FFI, OS threads and fibers, an LLVM native-code backend, a package manager, and a stepping debugger. The runtime uses a register-based bytecode VM with generational garbage collection and stack-copying first-class continuations, and was built with assistance from Anthropic's Claude AI.", "body_md": "A complete **R7RS-small** Scheme implementation, written in **Zig**.\n\n[Website](https://kaappi-lang.org/) ·\n[Playground](https://kaappi-lang.org/playground/) ·\n[Tour](https://kaappi-lang.org/tour/) ·\n[Guide](https://kaappi-lang.org/guide/) ·\n[Download](https://kaappi-lang.org/download/)\n\nKaappi implements every identifier from [R7RS Appendix A](https://small.r7rs.org/)\n— 641 built-in procedures, 32 syntax forms, and all 14 standard libraries — plus\n171 SRFIs, a C FFI, OS threads and fibers, an LLVM native-code backend, a package\nmanager, and a stepping debugger. The runtime is a register-based bytecode VM\nwith generational garbage collection and stack-copying first-class continuations.\n\nThe name is Malayalam and Tamil for *coffee* — see the\n[FAQ](https://kaappi-lang.org/faq/) for the story.\n\nNote:Kaappi was built with the assistance of AI (Claude by Anthropic).\n\nNo install needed — run Scheme in your browser at the\n[ playground](https://kaappi-lang.org/playground/), or take the guided\n12-lesson\n\n[.](https://kaappi-lang.org/tour/)\n\n**tour**\n\n```\ncurl -fsSL https://kaappi-lang.org/install.sh | bash\n```\n\nThis installs `kaappi`\n\nand `thottam`\n\n(the package manager) to `~/.local/bin/`\n\nand the standard libraries to `~/.kaappi/lib/`\n\n, verifying SHA256 checksums\nalong the way. On the BSDs the script works from the base system alone —\nwhen neither `curl`\n\nnor `wget`\n\nis installed it falls back to the base\n`fetch`\n\n(FreeBSD) or `ftp`\n\n(OpenBSD, NetBSD) for downloads and `sha256`\n\nfor verification.\n\nPrebuilt binaries for every platform are on the\n[releases page](https://github.com/kaappi/kaappi/releases/latest). macOS\nbinaries are Developer ID signed and notarized; all releases ship\n`SHA256SUMS`\n\nwith a GPG signature (`SHA256SUMS.asc`\n\n, key at\n[keybase.io/baijum](https://keybase.io/baijum)). See the\n[download page](https://kaappi-lang.org/download/) for manual install and\nverification steps.\n\nRequires **Zig 0.16+** and a C toolchain (for the vendored linenoise library):\n\n```\ngit clone https://github.com/kaappi/kaappi.git\ncd kaappi\nzig build                            # → zig-out/bin/kaappi\nzig build run                        # launch the REPL\nzig build run -- program.scm         # run a Scheme file\nzig build test                       # run the unit tests\n```\n\n| OS | Architecture | Build | Tests | Native compilation |\n|---|---|---|---|---|\n| macOS | aarch64 (Apple Silicon) | yes | yes | LLVM backend |\n| Linux | x86_64 | yes | yes | LLVM backend |\n| Linux | aarch64 | yes | yes | LLVM backend |\n| Linux | riscv64 | yes | yes | interpreter only |\n| Linux | s390x (big-endian) | yes | yes | interpreter only |\n| Linux | ppc64le | yes | yes | interpreter only |\n| Windows | aarch64 (ARM64), x86_64 | yes | yes | LLVM backend (needs a C toolchain) |\n| FreeBSD | x86_64, aarch64 | yes | yes | LLVM backend (base `cc` suffices) |\n| OpenBSD | x86_64, aarch64 | yes | yes | LLVM backend (base `cc` suffices) |\n| NetBSD | x86_64, aarch64 | yes | yes | LLVM backend (needs pkgsrc `clang` ; base `cc` is GCC) |\n| WebAssembly | wasm32-wasi | yes | — | interpreter only |\n\nThe WASM build (`zig build wasm`\n\n) runs in browsers and WASI runtimes — it\npowers the [playground](https://kaappi-lang.org/playground/).\n\nThe Windows port (`zig build -Dtarget=aarch64-windows`\n\nor\n`-Dtarget=x86_64-windows`\n\n) covers the full\ninterpreter — REPL (plain line editing, no history/completion), fibers,\nchannels, OS threads, FFI (`LoadLibrary`\n\n), and the `kaappi test`\n\nrunner.\nthottam installs packages on Windows too (with Git for Windows on PATH);\nonly manifests with a `build:`\n\ncommand are refused — the C-FFI packages'\nMakefiles target POSIX.\nPlatform differences: fd readiness covers sockets (event-driven,\nWSAEventSelect) and pipes (polled) — file ports keep blocking reads\n(timers and cross-thread wakeups always work) — and the POSIX-only\nslice of SRFI-170 (uid/gid, symlinks, chmod/umask, user/group info)\nraises a catchable file error. `cond-expand`\n\ndistinguishes the\nplatforms: Windows builds expose the `windows`\n\nfeature identifier\ninstead of `posix`\n\n.\n\nThe FreeBSD port (`zig build -Dtarget=x86_64-freebsd`\n\nor\n`aarch64-freebsd`\n\n) is full POSIX with no degradations: kqueue-backed\nfiber I/O, OS threads, complete SRFI-170, the full linenoise REPL, and\nthottam with `build:`\n\nsupport. `kaappi compile`\n\nlinks native binaries\nwith the base system's `cc`\n\n— no extra toolchain needed.\n\nThe OpenBSD port (`zig build -Dtarget=x86_64-openbsd`\n\nor\n`aarch64-openbsd`\n\n) is the same full-POSIX kqueue platform — fiber I/O,\nthreads, complete SRFI-170, the full REPL, `build:`\n\nsupport, and native\ncompilation with base `cc`\n\n. Two accommodations for OpenBSD's hardening,\nboth automatic: each binary is marked `PT_OPENBSD_NOBTCFI`\n\nat build time\nto opt out of BTCFI enforcement (Zig 0.16 emits no BTI landing pads), and\nthe interpreter raises its own stack limit at startup to clear OpenBSD's\ntight 4 MiB default. See [ docs/dev/openbsd.md](/kaappi/kaappi/blob/main/docs/dev/openbsd.md).\n\nThe NetBSD port (`zig build -Dtarget=x86_64-netbsd`\n\nor `aarch64-netbsd`\n\n)\ncompletes the BSD trio — the same full-POSIX kqueue feature set, verified\non NetBSD 10.1. The runtime binds NetBSD's versioned libc symbols\nexplicitly (`__kevent50`\n\n, `__opendir30`\n\n, `__getpwnam50`\n\n— the plain names\nare old-ABI compat symbols that silently misparse modern structs) and\nresets the aarch64 FPCR at startup, which NetBSD boots in flush-to-zero\nmode that would break IEEE gradual underflow. The native backend\n(`kaappi compile`\n\n) needs clang from pkgsrc — NetBSD's base `cc`\n\nis GCC,\nwhich can't consume LLVM IR. See [ docs/dev/netbsd.md](/kaappi/kaappi/blob/main/docs/dev/netbsd.md).\n\n``` bash\n$ kaappi\nkaappi> (define (fib n)\n  ...     (if (< n 2) n\n  ...         (+ (fib (- n 1)) (fib (- n 2)))))\nkaappi> (fib 20)\n6765\nkaappi> (map (lambda (x) (* x x)) '(1 2 3 4 5))\n(1 4 9 16 25)\nkaappi> `(the answer is ,(* 6 7))\n(the answer is 42)\nkaappi> (string-length \"héllo\")\n5\nkaappi> (char-alphabetic? #\\λ)\n#t\n```\n\nThe REPL has **syntax highlighting**, **line editing**, **persistent history**\n(`~/.kaappi/history`\n\n), **tab completion** for all built-in and user-defined\nsymbols, and **multi-line input** with automatic paren balancing.\n\n```\n(define-syntax my-when\n  (syntax-rules ()\n    ((my-when test body ...)\n     (if test (begin body ...)))))\n\n(my-when #t\n  (display \"hello world\")\n  (newline))\n(define-library (mylib math)\n  (export square cube)\n  (import (scheme base))\n  (begin\n    (define (square x) (* x x))\n    (define (cube x) (* x x x))))\n\n(import (mylib math))\n(cube 5) ;=> 125\n(define saved #f)\n\n(+ 1 (call/cc (lambda (k)\n                (set! saved k)\n                10)))\n;=> 11\n\n(saved 42)\n;=> 43\n```\n\n**Proper tail calls**—`(define (loop n) (loop (+ n 1)))`\n\nruns forever without growing the stack**First-class continuations**— multi-shot`call/cc`\n\nvia stack copying,`dynamic-wind`\n\nfor cleanup**Exception handling**—`guard`\n\n,`raise`\n\n,`with-exception-handler`\n\n, typed error objects (`file-error?`\n\n,`read-error?`\n\n)**Hygienic macros**—`syntax-rules`\n\nwith scope-based renaming; pattern variables, ellipsis, literals, underscore wildcards**Library system**—`define-library`\n\n,`import`\n\nwith`only`\n\n/`except`\n\n/`rename`\n\n/`prefix`\n\n,`.sld`\n\nfile loading,`cond-expand`\n\n**Numeric tower**— fixnum, bignum (arbitrary precision), exact rational, flonum (IEEE 754 f64), complex; automatic promotion on overflow** Full Unicode**— UTF-8 strings indexed by codepoint, Unicode character classification and case mapping** Records, ports, lazy evaluation, multiple values, parameters**— the whole standard, with no known functional gaps\n\n**171 SRFIs**— 12 built-in, 156 as portable`.sld`\n\nlibraries, plus SRFI 261 portable library references (`(srfi srfi-1)`\n\n,`(srfi lists-1)`\n\n) resolved in the importer and SRFI 226/160 as sub-libraries only (full list in[CONFORMANCE.md](/kaappi/kaappi/blob/main/CONFORMANCE.md))**Native binaries**—`kaappi compile program.scm -o program`\n\ncompiles Scheme to a native executable via LLVM, with self-tail-calls compiled as loops ([details](/kaappi/kaappi/blob/main/docs/dev/llvm-backend.md))**Standalone bundles**—`zig build -Dbundle-src=program.scm`\n\nembeds bytecode + libraries in a single executable**C FFI**— call shared libraries from Scheme via`(kaappi ffi)`\n\n; 18 marshalled types, callbacks for passing Scheme procedures to C**Concurrency**— green threads with channels via`(kaappi fibers)`\n\n, plus real OS threads via SRFI-18**Stepping debugger**— breakpoints (with conditions), watch expressions, step/next/step-out, frame navigation, locals — all from the REPL** Profiler**—`kaappi --profile`\n\nor`,profile expr`\n\n: per-function self/total time, call counts, allocation bytes**Sandbox mode**—`kaappi --sandbox`\n\nblocks FFI, file I/O,`eval`\n\n,`load`\n\n, and environment access**Bytecode caching**— compiled`.sbc`\n\nfiles are reused when the source is unchanged**Machine-legible diagnostics**— every error carries a stable`KP`\n\ncode (`error[KP3001]`\n\n), with`--diagnostics=json`\n\n(LSP shape),`kaappi explain <code>`\n\n, and a Scheme accessor`(error-object-code e)`\n\nin`(kaappi diagnostics)`\n\nfor dispatching on codes ([details](/kaappi/kaappi/blob/main/docs/dev/diagnostics.md))**Capability discovery**—`kaappi features [--json]`\n\nreports this build's version, target, compiled-in subsystems, SRFIs, and limits from one source of truth ([details](/kaappi/kaappi/blob/main/docs/dev/features.md))**Editor support**— a bundled LSP server (`kaappi-lsp`\n\n) and a[VS Code extension](https://github.com/kaappi/vscode-kaappi)\n\nKaappi ships **thottam**, a package manager for its growing library ecosystem:\n\n```\n# Install the web framework (auto-installs kaappi-http, kaappi-json, kaappi-net)\nthottam install kaappi-web\n\n# Now it just works — no --lib-path flags needed\nkaappi app.scm\n```\n\n| Package | Description |\n|---|---|\n|\n\n[kaappi-http](https://github.com/kaappi/kaappi-http)[kaappi-web](https://github.com/kaappi/kaappi-web)[kaappi-json](https://github.com/kaappi/kaappi-json)[kaappi-pg](https://github.com/kaappi/kaappi-pg)[kaappi-redis](https://github.com/kaappi/kaappi-redis)[kaappi-examples](https://github.com/kaappi/kaappi-examples)More libraries (CSV, TOML, YAML, logging, templates, testing, crypto, SQLite,\nemail, CLI parsing) are listed in the\n[ecosystem docs](https://kaappi-lang.org/ecosystem/).\n\n`thottam install <pkg>`\n\nresolves dependencies, supports version constraints\n(`thottam install kaappi-net@\">=0.2.0\"`\n\n), and installs to `~/.kaappi/lib/`\n\nwhere libraries are discovered automatically.\n\n```\n(import (kaappi web) (kaappi pg) (kaappi json))\n\n(define db (pg-connect \"dbname=myapp\"))\n\n(define app\n  (routes\n    (GET \"/users/:id\"\n      (lambda (req params)\n        (let ((rows (pg-query db \"SELECT * FROM users WHERE id = $1\"\n                      (param/number params \"id\"))))\n          (json-response (if (null? rows) '((\"error\" . \"not found\"))\n                             (car rows))))))\n    (POST \"/users\"\n      (lambda (req params)\n        (let ((body (request-json req)))\n          (pg-exec db \"INSERT INTO users (name) VALUES ($1)\"\n            (cdr (assoc \"name\" body)))\n          (json-response '((\"created\" . #t)) 201))))))\n\n(serve (wrap app wrap-json-body wrap-logging wrap-errors) 8080)\n```\n\nGreen threads (fibers) for cooperative multitasking within one OS thread:\n\n```\n(import (kaappi fibers))\n\n(define ch (make-channel))\n\n(spawn (lambda ()\n  (channel-send ch \"hello from fiber\")))\n\n(display (channel-receive ch))  ;=> hello from fiber\n```\n\nScheduling is cooperative: spawned fibers run when the main program blocks\n(`channel-receive`\n\non an empty channel, `fiber-join`\n\n) or calls `(yield)`\n\n.\nA fiber that blocks on an empty channel is parked and woken by the next\n`channel-send`\n\non that channel. When the main program ends, fibers that are\nstill parked (e.g. workers that never received a stop sentinel) are simply\ndiscarded and the process exits — like goroutines in Go. If the main program\nblocks on a channel that no runnable or parked-and-wakeable fiber can ever\nsend to, `channel-receive`\n\nraises a deadlock error (an `error`\n\nobject,\ncatchable with `guard`\n\n); the same applies to `fiber-join`\n\non a fiber that can\nnever complete.\n\nReal OS threads via SRFI-18 — each thread gets its own VM and GC, enabling true parallel I/O (e.g., thread-per-connection servers):\n\n```\n(import (srfi 18))\n\n(define t (thread-start!\n  (make-thread\n    (lambda ()\n      (display \"running on OS thread\")\n      (newline)))))\n\n(thread-join! t)\nSource → Reader → Expander → IR → Bytecode emission → VM\n         (UTF-8    (syntax-   (analysis +   (register-    (generational GC,\n          lexer)    rules)     optimization   based)        stack-copied\n                               passes)                      continuations)\n```\n\n| Component | Role |\n|---|---|\nReader |\nTokenizer + recursive descent parser for the full R7RS lexical syntax, including Unicode identifiers and `#\\λ` character literals. |\nExpander |\n`syntax-rules` pattern matching and hygienic template instantiation. |\nIR |\nTree-structured intermediate representation (33 node types) with analysis passes (tail positions, primitives, constants) and optimization passes (constant folding, dead-branch elimination, and more). |\nCompiler |\nIR → register-based bytecode. |\nVM |\nBytecode interpreter with growable register file and frame stack, exception handler and dynamic-wind stacks, stack-copying continuations, and a stepping debugger. |\nGC |\nGenerational collector (young/old) with write barrier for old→young references. |\n\nValues are **NaN-boxed 64-bit words** — flonums, fixnums, booleans, characters,\nand nil all fit in a single u64 with zero heap allocation:\n\n```\nFlonum:    any f64 that is not a NaN     ← stored directly\nPointer:   0xFFFC | 48-bit pointer       ← heap object\nFixnum:    0xFFFD | 48-bit signed int    ← up to ±2^47, auto-promotes to bignum\nImmediate: 0xFFFE | payload              ← nil, bool, void, eof, char\n```\n\nThe full component map, file layout, and design notes are in\n[docs/dev/architecture.md](/kaappi/kaappi/blob/main/docs/dev/architecture.md).\n\n```\nzig build test                     # Zig unit tests\nbash tests/scheme/run-all.sh       # all Scheme-level suites\n```\n\nThe Scheme suites include a 1,391-test R7RS conformance suite (via\n`(chibi test)`\n\n), plus targeted suites for compliance, continuations, macro\nhygiene, SRFIs, and the FFI. CI runs on every platform in the support matrix,\nand per-commit performance trends are tracked on the\n[benchmark dashboard](https://kaappi-lang.org/kaappi/dev/bench/).\n\n| Document | Description |\n|---|---|\n|\n\n[Procedure Reference](https://kaappi-lang.org/procedures/)[Cookbook](https://kaappi-lang.org/cookbook/)[Ecosystem](https://kaappi-lang.org/ecosystem/)[R7RS Conformance](/kaappi/kaappi/blob/main/CONFORMANCE.md)[Architecture](/kaappi/kaappi/blob/main/docs/dev/architecture.md)[Adding Features](/kaappi/kaappi/blob/main/docs/dev/adding-features.md)[Testing Guide](/kaappi/kaappi/blob/main/docs/dev/testing.md)[Developer Docs Index](/kaappi/kaappi/blob/main/docs/dev/README.md)`call/cc`\n\ncaptures continuations by copying the full VM state (registers, call\nframes, exception handlers, dynamic-wind stack). Cost is O(stack depth) per\ncapture — negligible for most programs, but noticeable if continuations are\ncaptured in tight inner loops. Continuations captured in one top-level REPL\nexpression cannot re-enter subsequent top-level expressions (standard behavior\nshared by Guile, Chibi, Chicken, Chez, and Racket).\n\nSRFI 248's delimited continuations (`with-unwind-handler`\n\n, and the extended\n`guard`\n\n) are built on this `call/cc`\n\nvia a sticky exception handler, with two\nobservable caveats:\n\n**Single-shot**— each captured delimited continuation may be resumed at most once. Every SRFI 248 idiom (coroutine generators,`for-each->fold`\n\n, effect handlers) resumes each`k`\n\nonce, so this does not affect them; resuming the same`k`\n\ntwice fails because it re-enters a native frame that has already returned.**Handler timing**— the handler runs at the raise point rather than after unwinding to`with-unwind-handler`\n\n, so a handler side effect (and, since`guard`\n\nis built on it, a`guard`\n\nclause) runs*before*a`dynamic-wind`\n\nafter-thunk of the guarded body, where R7RS-small runs it after. All the effects still happen; only their order differs. See[CONFORMANCE.md](/kaappi/kaappi/blob/main/CONFORMANCE.md)for details.\n\nBoth are limited to SRFI 248; plain `call/cc`\n\n, `dynamic-wind`\n\n, and the built-in\n`guard`\n\nare unaffected unless you import `(srfi 248)`\n\n.\n\nCallbacks driven by `map`\n\n, `for-each`\n\n, `vector-map`\n\n, `vector-for-each`\n\n,\n`string-map`\n\n, `string-for-each`\n\n, `dynamic-wind`\n\n, and `force`\n\nrun in the\nbytecode dispatch loop, so a fiber can park inside them (e.g. block on an\nempty channel) and resume later. Other higher-order procedures are still\nnative drivers — SRFI-1 (`fold`\n\n, `filter`\n\n, `find`\n\n, `any`\n\n, `every`\n\n, ...),\n`sort`\n\n, `hash-table-walk`\n\n/`hash-table-update!`\n\n, `assoc`\n\n/`member`\n\nwith a\ncustom predicate, `string-index`\n\n, `eval`\n\n, ... — and a fiber that blocks on\nan empty channel inside one of those callbacks cannot be parked: the native\ncall's state lives on the Zig stack and cannot be suspended. If other fibers\nare runnable the scheduler still makes progress, but if the blocked receive\nis the only thing left it raises a deadlock error instead of suspending.\nMove blocking `channel-receive`\n\ncalls into plain Scheme loops (named `let`\n\n,\n`do`\n\n) or the bytecode-driven procedures above when a fiber must wait inside\niteration.\n\nPort I/O that would block (a socket or pipe read/write with no data or a\nfull kernel buffer) parks the fiber on the per-thread reactor instead of\nblocking the OS thread, so fibers reading different connections interleave.\nThe main fiber — or a fiber inside a native-driver callback — cannot be\nparked; it instead dispatches sibling fibers in place while it waits, so\nprogress continues either way. Ports on fds other than 0/1/2 buffer output\nuntil `flush-output-port`\n\n, `close-port`\n\n, a read on the same port, the\nbuffer filling (8 KiB), or program exit; stdin/stdout/stderr remain\nunbuffered. WASI builds keep blocking single-fiber I/O (the reactor's WASI\nbackend is timer-only until KEP-0001 Phase 4).\n\nEach OS thread gets its own GC with an independent heap. Values are deep-copied\nwhen crossing thread boundaries (at `thread-start!`\n\nand `thread-join!`\n\n). This\nmeans threads cannot share mutable state directly — use channels or return\nvalues to communicate. Child threads can allocate and GC independently without\naffecting the parent.\n\nA `(kaappi fibers)`\n\nchannel captured by a thread's thunk (or nested inside a\nvalue sent over one) crosses safely: it is promoted to a mutex-protected,\nrefcounted shared channel outside every GC heap, and every message crosses by\ncopy (KEP-0002). `(kaappi parallel)`\n\nbuilds worker pools and `parallel-map`\n\n/\n`parallel-for-each`\n\non top of this — see the [Concurrency\nguide](https://kaappi-lang.org/guide/concurrency/) for the higher-level API.\nA channel reached through a shared global instead (not captured by a thunk or\nmessage) still raises a descriptive error rather than corrupting memory. Two\nnarrow correctness issues are open in the cross-thread wakeup path\n([#1487](https://github.com/kaappi/kaappi/issues/1487),\n[#1489](https://github.com/kaappi/kaappi/issues/1489)) — not yet recommended\nfor production concurrent workloads. See [Standards\nConformance](https://kaappi-lang.org/conformance/#extensions-beyond-r7rs-smalls-scope)\nfor current status.\n\nA closure that crosses a `thread-start!`\n\nboundary must not, once running on\nthe other thread, *call* a separately-defined top-level procedure from a\nlibrary — doing so hangs\n([#1520](https://github.com/kaappi/kaappi/issues/1520)). The identical logic\ninlined directly into the closure works correctly; `(kaappi parallel)`\n\n's own\nworker loop is written this way for exactly this reason.\n\n`parallel-map`\n\n/`parallel-for-each`\n\nsubmit one task per list element, so a\nlarge list means many concurrent `pool-submit`\n\n/`task-wait`\n\nround trips —\nwhich, given #1487/#1489 above, means an intermittent hang becomes\nincreasingly likely somewhere past a few hundred concurrent submissions\nrather than a hard cutoff. Reliable in testing through list sizes in the\nlow hundreds. For larger inputs, chunk manually with\n`make-pool`\n\n/`pool-submit`\n\n/`task-wait`\n\n(one task per processor, each\ncovering a slice of the input with an ordinary sequential loop) instead of\none task per element — see `kaappi-examples/parallel-primes`\n\nfor a worked\nexample.\n\nOnly `syntax-rules`\n\nis supported. `syntax-case`\n\nwas intentionally excluded from\nR7RS-small and is not implemented.\n\n171 SRFIs are supported. Some built-in SRFIs have minor coverage gaps (e.g.,\nlinear-update variants in SRFI-1, `string-xcopy!`\n\nin SRFI-13). See\n[CONFORMANCE.md](/kaappi/kaappi/blob/main/CONFORMANCE.md) for per-SRFI details.\n\nSRFI 261 (Portable SRFI Library Reference) is supported as an import-resolver\nconvention: `(import (srfi srfi-1))`\n\nand `(import (srfi lists-1))`\n\nresolve to\n`(srfi 1)`\n\n— the trailing number is authoritative — and sub-library tails pass\nthrough (`(srfi srfi-146 hash)`\n\n). Literal names win when they exist, so a\nlibrary actually named `(srfi srfi-x)`\n\nis never shadowed. `cond-expand`\n\n's\n`(library …)`\n\ntest honors the same forms.\n\nContributions are welcome — bug reports, SRFI implementations, documentation, and ecosystem libraries alike.\n\n**New here?** Start with\n[GitHub Discussions](https://github.com/orgs/kaappi/discussions) — ask\nquestions, report bugs, propose ideas. Issues and PRs are open to\n[org members](https://github.com/kaappi); request an invite in Discussions\nwhen you're ready to contribute directly.\n\n[CONTRIBUTING.md](/kaappi/kaappi/blob/main/CONTRIBUTING.md)— how to get involved, build, test, and submit changes[Community](https://kaappi-lang.org/community/)— all the ways to participate[Code of Conduct](/kaappi/kaappi/blob/main/CODE_OF_CONDUCT.md)\n\nEvery bug fix needs a regression test; see the\n[testing guide](/kaappi/kaappi/blob/main/docs/dev/testing.md).", "url": "https://wpnews.pro/news/kaappi-r7rs-scheme-written-in-zig", "canonical_source": "https://github.com/kaappi/kaappi", "published_at": "2026-07-26 05:18:10+00:00", "updated_at": "2026-07-26 05:52:42.227657+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence"], "entities": ["Kaappi", "Zig", "R7RS-small", "LLVM", "Anthropic", "Claude"], "alternates": {"html": "https://wpnews.pro/news/kaappi-r7rs-scheme-written-in-zig", "markdown": "https://wpnews.pro/news/kaappi-r7rs-scheme-written-in-zig.md", "text": "https://wpnews.pro/news/kaappi-r7rs-scheme-written-in-zig.txt", "jsonld": "https://wpnews.pro/news/kaappi-r7rs-scheme-written-in-zig.jsonld"}}