{"id":18717366,"url":"https://github.com/rekola/nanoclj","last_synced_at":"2025-10-13T22:10:19.400Z","repository":{"id":187434160,"uuid":"674631979","full_name":"rekola/nanoclj","owner":"rekola","description":"A Tiny Clojure Interpreter","archived":false,"fork":false,"pushed_at":"2024-12-29T16:31:56.000Z","size":3672,"stargazers_count":73,"open_issues_count":31,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-09T18:19:15.545Z","etag":null,"topics":["c","clojure","cplusplus","interpreter"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rekola.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null}},"created_at":"2023-08-04T12:18:21.000Z","updated_at":"2025-04-05T17:55:58.000Z","dependencies_parsed_at":"2023-08-10T12:10:27.026Z","dependency_job_id":"4455ca5a-82d4-4f81-8957-ee2a2969b899","html_url":"https://github.com/rekola/nanoclj","commit_stats":null,"previous_names":["rekola/nanoclj"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rekola%2Fnanoclj","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rekola%2Fnanoclj/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rekola%2Fnanoclj/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rekola%2Fnanoclj/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rekola","download_url":"https://codeload.github.com/rekola/nanoclj/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248085325,"owners_count":21045139,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","clojure","cplusplus","interpreter"],"created_at":"2024-11-07T13:15:54.339Z","updated_at":"2025-10-13T22:10:14.345Z","avatar_url":"https://github.com/rekola.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nanoclj\n\n[![CI](https://github.com/rekola/nanoclj/workflows/Ubuntu-CI/badge.svg)]()\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)\n\n## A Tiny Clojure Interpreter\n\nThis is a small Clojure language implementation written in C\nlanguage. It is based on TinyScheme which was based on MiniScheme. The\nproject is in the early stages yet, and much functionality is still\nmissing. The project has two main goals:\n\n1. Provide data visualization capabilities for the REPL in a terminal or GUI.\n2. Provide an embedded Clojure interpreter for C++ applications as an alternative for Lua and other scripting languages.\n\nAn additional long term goal is to bring AI assistance right in to the REPL.\n\n## Features\n\n- Terminal graphics (*Kitty* or *Sixel* protocols) with HiDPI support\n- Image, audio, Shapefile, XML, CSV and GraphML loading\n- Simple image operations (blur, transpose etc.) and 2D canvas\n- REPL output is colored by type\n- Callback Writer for printing into a GUI instead of stdout\n- Class and namespace names try to imitate Java and Clojure names when possible (e.g. `(type 1) ;=\u003e java.lang.Long`)\n- BigInts and Ratios\n- Tensors are used for representing most data structures. For example, a vector is a 1D tensor of doubles (with NaN-packing for other data types).\n- Test framework\n\n### 2D Graphics\n\nSince Clojure has no standard way for 2D drawing, a new system has\nbeen created for nanoclj. The principle of minimality suggests that\nthere should only be a single way to output text, which means that\nprintln must work with canvas. Therefore, an active canvas is bound to\n`*out*` and it's the target of all canvas operations. For normal `*out*`\nthe canvas commands are ignored (apart from color and restore), but\none could imagine that they could be used to draw vector graphics on a\nTektronix terminal, or move-to could set the cursor position in a text\nmode program. The canvas interface has been modeled after Cairo.\n\nIn GUI program the resulting canvas can be displayed in a REPL using\nthe GUI callbacks for output Writer. In terminal program Kitty or\nSixel protocol is used to print the results of a function call when\nthe function returns a canvas or image. The terminal must, of course,\nneed to support Kitty or Sixel graphics and support must be\nenabled. The following terminals have been tested:\n\n| Terminal | Graphics | Mouse | Notes |\n| - | - | - | - |\n| foot | OK | OK | Wayland only, no undercurls |\n| kitty | OK | ? | True color images, but window resizing has bugs (as of 0.26.5) |\n| wezterm | OK | OK | Buggy (as of 20230712) |\n| mlterm | OK | ? | linenoise output flickers when updated, no undercurls |\n| Konsole | OK | ? | True color images, but on HiDPI system images are upscaled |\n| contour | Inline image layout doesn't work | ? | |\n| xterm | No true color\t| OK | No undercurls, Sixel support must be enabled in `.Xresources`, and images have maximum size 1000x1000 |\n| Black Box | Inline image layout doesn't work | ? | On HiDPI system the images are upscaled, and the terminal and the flatpak system use too much CPU time when idling. |\n| Alacritty | None | ? | |\n| GNOME Terminal | None | ? | Sixel support is not enabled by default |\n| mintty | ? | ? | Not tested yet. |\n\n![Plotting from nanoclj](https://github.com/rekola/nanoclj/assets/6755525/194a6914-f87a-446f-8bae-53b12c75b327 \"Plotting from nanoclj\")\n*The plot function returns a canvas, which can be saved with nanoclj.image/save or modified using other functions in the nanoclj.image namespace.*\n\nAs well as printing images in block mode like the plot function does, they can also be printed in inline mode which is shown in the following example:\n\n![Inline gradients](https://github.com/rekola/nanoclj/assets/6755525/74249581-0fb5-4433-9761-15b97385ee3c \"Inline gradients\")\n\n## Differences to Clojure:\n\n- Characters are 32 bit, strings are UTF-8 (count is O(n)), UTF8 validity is checked and char-array creates a byte array\n- Strings are sequences, and they are compared and sorted as such.\n- List count has complexity of O(n)\n- Macros use the TinyScheme syntax\n- Tail-call optimization\n- sort is not stable and doesn't support custom compare function\n- License is BSD 3-Clause License instead of EPL\n- Symbols are interned but are temporarily boxed when metadata is added\n- Primitives such as doubles and small integers are passed by value, and are in effect, interned\n- Regular expressions are interned, but strings are not: `(identical? \"abc\" \"abc\") ;=\u003e false`\n- `rationalize` returns exact result for doubles: `(rationalize 0.1) ;=\u003e 3602879701896397/36028797018963968`\n- No chunked or buffered lazy sequences\n- Data structures are only partially persistent, and while vectors, maps and sets allow fast reading and insertion, deletion and modification is slow.\n- Namespaces can only contain Vars, not Classes: `(resolve 'Math) ;=\u003e #'java.lang.Math`\n- Arrays are compared by value, can only contain primitive values (including Objects) and multidimensional arrays cannot be ragged\n- No type hints\n- Unbound Vars cannot be created\n- Dividing Long/MIN_VALUE by -1 doesn't fail\n- java.net.URL doesn't resolve the hostname for calculating hashcode\n- No transient data structures\n\n## Dependencies\n\n- linenoise (included, extra functionality such as UTF8 support and brace highlighting added)\n- stb_image, stb_image_resize, stb_image_write (included)\n- dr_wav (included)\n- zlib\n- libxml2\n- pcre2\n- cairo\n- libsixel\n- utf8proc\n- shapelib\n\n## Building\n\nC11 support is required for building nanoclj, and it has been tested with both gcc and clang. Both 32-bit and 64-bit systems are supported.\n\n### Ubuntu\n\n```\nsudo apt install libutf8proc-dev libsixel-dev libpcre2-dev libcairo2-dev libshp-dev libcurl4-gnutls-dev libxml2-dev libz-dev\nmkdir build\ncd build\ncmake ..\nmake\nsudo make install\n```\n\n### Arch Linux PKGBUILD\n\n```\ncurl https://raw.githubusercontent.com/rekola/nanoclj/main/PKGBUILD -O\nmakepkg -si\n```\n\n### Windows\n\nWindows support is in progress.\n\n## Missing functionality\n\n- Interfaces, Records, StructMaps, Protocols and Multi-methods\n- Dynamic variables\n- Transducers\n- Refs, Agents, Atoms, Validators\n- Reader Conditionals\n- BigDecimals, 32-bit floats and hexadecimal floating point literals\n- Locals cleaning\n- Multithreading, transactions, STM and locking\n- Pre- and post-conditions for functions\n- Readers and Writers do not accept options such as :encoding or :append\n- Associative destructuring\n- Map namespace syntax\n- `*print-length*`, `*print-level*`, `*clojure-version*`, `*load-tests*`\n- Missing core functions and macros\n  - doseq, for\n  - sorted-set-by, sorted-set, sorted-map, sorted-map-by\n  - update-in, merge-with\n  - doto, -\u003e, --\u003e, some-\u003e, some-\u003e\u003e\n  - map-indexed, mapcat, lazy-cat\n  - partition-by\n  - memoize\n  - condp\n  - load\n  - when-let, letfn, if-let, if-some\n  - reduced, reduced?\n  - with-local-vars, var-set, find-var, alter-var-root, declare, binding, with-bindings\n  - sequence, subseq, rsubseq\n  - make-hierarchy, ancestors, supers, bases, underive\n  - re-groups, re-matcher, re-seq, re-matches\n  - assert-args\n  - trampoline\n  - shuffle, random-sample\n  - unchecked-byte, unchecked-short, unchecked-char, unchecked-int, unchecked-long, unchecked-float, unchecked-double\n  - vary-meta, alter-meta!\n  - aset-char, aset-long, amap, areduce, to-array-2d, make-array, long-array, bytes?\n  - remove-ns, ns-imports, ns-interns, ns-aliases, ns-unalias, ns-unmap\n- clojure.java.io\n  - resource\n  - make-parents\n  - delete-file\n- clojure.repl\n  - dir\n- clojure.test\n  - deftest, set-test, with-test\n- clojure.math\n- clojure.core.async (thread, thread-call etc.)\n- clojure.core.reducers\n- clojure.main (load-script etc.)\n- clojure.pprint (print-table etc.)\n- clojure.data\n- clojure.walk\n- clojure.zip\n- clojure.spec\n- ...and lots more...\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frekola%2Fnanoclj","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frekola%2Fnanoclj","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frekola%2Fnanoclj/lists"}