{"id":23011488,"url":"https://github.com/thecodesojourner/cljonic","last_synced_at":"2025-04-02T17:10:32.968Z","repository":{"id":268029369,"uuid":"903054139","full_name":"TheCodeSojourner/cljonic","owner":"TheCodeSojourner","description":"Header-Only Embedded-Systems C++ Clojure-esque Functional Programming Library","archived":false,"fork":false,"pushed_at":"2025-02-12T21:28:13.000Z","size":9065,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-12T22:25:14.052Z","etag":null,"topics":["clojure","cpp","cpp20","embedded","embedded-systems","functional-programming","header-only"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TheCodeSojourner.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-13T20:44:04.000Z","updated_at":"2025-01-30T16:41:13.000Z","dependencies_parsed_at":"2024-12-28T23:21:11.567Z","dependency_job_id":"ceb7f064-92dc-4bcc-ac30-a54a15038a87","html_url":"https://github.com/TheCodeSojourner/cljonic","commit_stats":null,"previous_names":["thecodesojourner/cljonic"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheCodeSojourner%2Fcljonic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheCodeSojourner%2Fcljonic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheCodeSojourner%2Fcljonic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheCodeSojourner%2Fcljonic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TheCodeSojourner","download_url":"https://codeload.github.com/TheCodeSojourner/cljonic/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246856675,"owners_count":20844974,"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":["clojure","cpp","cpp20","embedded","embedded-systems","functional-programming","header-only"],"created_at":"2024-12-15T10:09:07.431Z","updated_at":"2025-04-02T17:10:32.944Z","avatar_url":"https://github.com/TheCodeSojourner.png","language":"C++","readme":"= cljonic \n:doctype: book\n:source-highlighter: rouge\n:cpp: C++\n\nimage::logo.png[cljonic, 200, 200, align=\"center\"]\n\n[.text-center]\n*Header-Only Embedded-Systems C++ Clojure-esque Functional Programming Library*\n\nNOTE: If you are interested in a \"big-machine\" *{cpp} Clojure* implementation see the https://github.com/jank-lang/jank[Jank] project.\n\nIMPORTANT: I am *NOT* a *Modern {cpp}* expert. I'm learning *Modern {cpp}*, especially *Concepts*, using \n*github Copilot*. I'm moderately competent in *Clojure*, having used it professionally for several years. If you have \nsuggestions for improvement, *PLEASE* feel free to create issues, and I'll *do my best* to address them. *PRs* \nare also welcome.\n\n== Pronunciation\n[.big]#*cljonic* /klə-jŏn′ĭk/#\n\n== Obligatory Word Definition\n\n[.big]#*Laconic*#\n\n* Expressing much in few words; brief and pithy; concise; brusque\n\n== Detailed Documentation\nDetailed documentation is available https://thecodesojourner.github.io/cljonic/[here].\n\n== Motivation\n\n.*John Carmack* - https://www.gamedeveloper.com/programming/in-depth-functional-programming-in-c-\n____\n\"A large fraction of the flaws in software development are due to programmers not fully understanding all the\npossible states their code may execute in. ... Programming in a functional style makes the state presented to your code \nexplicit, which makes it much easier to reason about [(i.e., Fewer mistakes, and less debugging)] ...\n\nNo matter what language you work in, programming in a functional style provides benefits. You should do it whenever it \nis convenient, and you should think hard about the decision when it isn't convenient.\"\n____\n\n*Clojure* is one of the most expressive and concise programming languages. It is *laconic* in nature, \n*immutable-by-default*, *practical*, and *stable*. *Clojure* is based on the *Lisp* programming language. However, \n*Clojure* is not well suited for some programming domains, such as *embedded systems* with tight memory and CPU \nconstraints that do not allow *heap* usage and only offer *{cpp}* programming tools.\n\n*{cpp}*, on the other hand, is quite different from *Clojure*. It tends to be *verbose* rather than *laconic*. *{cpp}* \nis not immutable-by-default and is not considered a functional programming language, although it has some functional \nfeatures like *lambdas* and standard libraries such as *ranges*, *views*, *optional*, and *expected*. *{cpp}* is a \n*BIG* language that is constantly evolving, with a large and growing feature set. It offers many ways to do things, \nsome of which make it easy to do things poorly.\n\nMost *embedded system developers* are not computer language experts. They do not have time to keep up with the latest \n*{cpp}* language features, and their educational background is often not heavy in the nuances of optimal *Modern* \n*{cpp}* usage. When it comes to *Modern* *{cpp}*, they are often mostly *self-taught* and have learned on the job.\n\nSome *embedded system* projects do not require heavy use of the *{cpp}* features designed for memory and CPU utilization \noptimization. Many projects have a small amount of code that must be *finely tuned*, and quite a bit of code that is \n*not performance critical*.\n\nThe motivation behind *cljonic* is to provide a *Clojure-esque* functional programming library for *{cpp}* embedded \nsystem developers. It aims to be *laconic*, *immutable-by-default*, *practical*, and *stable*. *Cljonic* should also be \n*easy to learn and understand*, and *easy to use properly* for the *safe* and *efficient* implementation of embedded \nsystems.\n\n== Desired Developer Experience When Using cljonic\nThe developer using *cljonic* should be able to write *safe* code that is *easy to read*, *easy to understand* and \n*easy to maintain*.  These goals will enable *embedded system* projects to be *completed more quickly*, with \n*fewer bugs*, and maintained and enhanced with *less long term effort*. \n\n=== Default Element\nEvery *cljonic collection* has a *default element* that is returned whenever a valid collection element can't be returned.\nThe value of a collection's *default element* is a default initialized instance of the type of the collection's values\n(i.e., T{}).  This approach is taken to avoid using exceptions and/or error codes/states.\n\nNOTE: The design choice to use a *default element* means that *cljonic* users must take care to ensure that they know\nwhen a *default element* can be returned (e.g., Asking for the First element of an empty collection), and to handle things appropriately. \n\n=== constexpr\n*cljonic* uses *constexpr* whenever possible to enable *compile-time* evaluation of expressions. Additionally, this \napproach helps to dectect *undefined behavior* at compile time.\n\n== Developer Experience When Developing cljonic\n*cljonic* has a *Makefile* in the root directory.  For *help* on the available development processes simply execute \n`make` from a command-line while in the root directory to generate a list of the available options.\n\n*After cloning the repository*, the developer should first execute `make all`. Next, assuming no files are added to the\nrepository, only modified, the developer should execute `make test`. Assuming all tests pass, executing `make cljonic` \nwill generate the *cljonic* single header file.  Finally, executing `make git` will prepare the repository for a *git* \ncommit.\n\nNOTE: Whenever new files are added to the *code/source* or *code/test* directories the developer must run `make all` \nagain.\n\nNOTE: Whenever new function files are added to the *code/source* directory the developer must update the \n*code/source/cljonic-pre-declarations.hpp*, *scripts/make-cljonic.sh*, and *resources/no-dynamic-memory.cpp* files \nto include support for the new function.\n\n== Implementation Characteristics\n\nNOTE: The performance of the implementation should be acceptable if the *average collection size is small*, and the \n*cljonic* library is used for *non-performance-critical code*.\n\n* In order to provide the *cljonic immutable-by-default* feature, and because the *heap* can't be used in the *targeted* \nembedded systems, *cljonic* uses copying.  \n\n* In order to meet the *safe* Desired Developer Experience goal, *cljonic* does bounds-checking on all collection\naccesses. \n\n* In order to meet the *safe* Desired Developer Experience goal, *cljonic* provides a *#define* named *CLJONIC_COLLECTION_MAXIMUM_ELEMENT_COUNT* that specifies the maximum number of elements that can be stored in a *cljonic Collection*, which is defaulted to *1000*. *CLJONIC_COLLECTION_MAXIMUM_ELEMENT_COUNT* can be changed to a larger value if needed by adding a line of code like this \"*#define CLJONIC_COLLECTION_MAXIMUM_ELEMENT_COUNT 10000*\" before including *cljonic.hpp*, by directly defining *CLJONIC_COLLECTION_MAXIMUM_ELEMENT_COUNT* on the compiler command line, or by indirectly defining *CLJONIC_COLLECTION_MAXIMUM_ELEMENT_COUNT* in a build tool like *cmake*.\n\n== Required Resources\n* *AsciiDoc* for project documentation\n** https://asciidoctor.org/docs/asciidoc-writers-guide/\n* *C++ 20*, or higher, for *Modern {cpp}* features\n* *catch* v2.13.9 for testing\n* *clang-format* for code formatting\n* *cppcheck* for code analysis\n* *doxygen* for code documentation\n* *gcov* for code coverage analysis\n* *genhtml* for code coverage analysis\n* *lcov* for code coverage analysis\n* *lizard* for code metrics\n** https://github.com/terryyin/lizard\n** According to the lizard documentation, it only supports C++14. Another tool that supports *Cyclomatic Complexity* and *Function LoC* would be better.\n* *valgrind* for code analysis","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthecodesojourner%2Fcljonic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthecodesojourner%2Fcljonic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthecodesojourner%2Fcljonic/lists"}