summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Orst <andreyorst@gmail.com>2021-01-19 16:46:00 +0000
committerAndrey Orst <andreyorst@gmail.com>2021-01-19 16:46:00 +0000
commit270beed0505ef47159d94fb162ff4840958f3ce5 (patch)
tree6504ecb114419b0dd3055e509abd8b602586f614
parenta2b08f721c28b3b56a802031bc35df6a68b219d8 (diff)
fix: Fennel 0.8.0 enhancements
Changelog: - fixed bug in try - reworked pretty printing for sets - handle cycles in sets - use new fennel.view format - reorganized library to make requiring it easier
-rw-r--r--.depend.mk8
-rw-r--r--.dir-locals.el23
-rw-r--r--.gitlab-ci.yml38
-rw-r--r--CODE_OF_CONDUCT.md5
-rw-r--r--CODE_OF_CONDUCT.org5
-rw-r--r--CONTRIBUTING.md85
-rw-r--r--CONTRIBUTING.org94
-rw-r--r--Makefile15
-rw-r--r--README.md40
-rw-r--r--README.org14
-rw-r--r--doc/cljlib.md251
-rw-r--r--doc/macros.md (renamed from doc/cljlib-macros.md)23
-rw-r--r--doc/tests/test.md2
-rw-r--r--init.fnl (renamed from cljlib.fnl)145
-rw-r--r--macros.fnl (renamed from cljlib-macros.fnl)165
-rw-r--r--tests/core.fnl1039
-rw-r--r--tests/fn.fnl27
-rw-r--r--tests/macros.fnl20
-rw-r--r--tests/test.fnl44
19 files changed, 1072 insertions, 971 deletions
diff --git a/.depend.mk b/.depend.mk
index 1c09089..a93e35b 100644
--- a/.depend.mk
+++ b/.depend.mk
@@ -1,4 +1,4 @@
-cljlib.lua: cljlib.fnl cljlib-macros.fnl
-tests/core.lua: tests/core.fnl cljlib-macros.fnl tests/test.fnl cljlib.fnl
-tests/macros.lua: tests/macros.fnl cljlib-macros.fnl tests/test.fnl
-tests/fn.lua: tests/fn.fnl cljlib-macros.fnl tests/test.fnl
+init.lua: init.fnl macros.fnl
+tests/core.lua: tests/core.fnl macros.fnl tests/test.fnl init.fnl
+tests/macros.lua: tests/macros.fnl macros.fnl tests/test.fnl
+tests/fn.lua: tests/fn.fnl macros.fnl tests/test.fnl
diff --git a/.dir-locals.el b/.dir-locals.el
index 6036615..bf3fb90 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -1,7 +1,28 @@
;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")
-((fennel-mode . ((eval . (put 'when-meta 'fennel-indent-function 'defun))
+((fennel-mode . ((eval . (font-lock-add-keywords
+ 'fennel-mode
+ `((,(rx word-start
+ (group (or "fn*"
+ "try"
+ "if-let"
+ "if-some"
+ "when-let"
+ "when-some"
+ "empty"
+ "into"
+ "when-meta"
+ "with-meta"
+ "meta"
+ "meta"
+ "def"
+ "defmulti"
+ "defmethod"
+ "defonce"))
+ word-end)
+ 1 'font-lock-keyword-face))))
+ (eval . (put 'when-meta 'fennel-indent-function 'defun))
(eval . (put 'defmethod 'fennel-indent-function 'defun))
(eval . (put 'defmulti 'bfennel-indent-function 'defun))
(eval . (put 'deftest 'fennel-indent-function 'defun))
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index fd30085..a49ff33 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -4,34 +4,42 @@ stages:
- test
- coverage
-Lua 5.3:
- image: alpine:3.12.1
+Lua:
+ image: alpine:edge
stage: test
before_script:
- - apk add lua5.3 luarocks5.3 make
- - luarocks-5.3 install fennel
+ - apk add -q lua5.2 lua5.3 lua5.4 git make
+ - git clone https://git.sr.ht/~technomancy/fennel
+ - (cd fennel; LUA=lua5.3 make install)
script:
- - LUA=lua5.3 make test
+ - LUA_EXECUTABLES="lua5.2 lua5.3 lua5.4" make testall >/dev/null
-Lua 5.4:
- image: ubuntu:20.10
+# Luajit actually is an impostor in Alpine, as the package actually
+# uses Moonjit implementation, which is different from what I'm
+# working with, so Fedora 33 image is used, which as of this moment
+# has latest Luajit available
+Luajit:
+ image: fedora:33
stage: test
before_script:
- - ln -snf /usr/share/zoneinfo/Europe/Moscow /etc/localtime
- - echo Europe/Moscow > /etc/timezone
- - apt-get update && apt-get install -y lua5.4 luarocks make >/dev/null
- - luarocks install fennel
+ - dnf install -y -q lua luajit git make
+ - git clone https://git.sr.ht/~technomancy/fennel
+ - (cd fennel; make install)
script:
- - LUA=lua5.4 make test
+ - LUA=luajit make test
+# We install fennel via luarocks by making local rockspect because I
+# don't want to figure out how to install luacov without luarocks
Coverage:
image: alpine:3.12.1
stage: coverage
before_script:
- - apk add lua5.3 lua5.3-dev gcc musl-dev luarocks5.3 make
- - luarocks-5.3 install fennel
+ - apk add -q lua5.3 lua5.3-dev gcc musl-dev luarocks5.3 git make
+ - (cd $HOME; git clone https://git.sr.ht/~technomancy/fennel)
+ - export LUA=lua5.3
+ - (cd $HOME/fennel; luarocks-5.3 make rockspecs/fennel-scm-2.rockspec)
- luarocks-5.3 install luacov
- luarocks-5.3 install luacov-console
script:
- - LUA=lua5.3 make luacov-console
+ - make luacov-console >/dev/null
- luacov-console --no-colored -s
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..ca3f99e
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,5 @@
+Only **code quality** does matter.
+
+Everything else is up to your personal taste.
+
+However, this doesn't mean that we will be tolerant to *any* kind of antics.
diff --git a/CODE_OF_CONDUCT.org b/CODE_OF_CONDUCT.org
deleted file mode 100644
index ad2e2da..0000000
--- a/CODE_OF_CONDUCT.org
+++ /dev/null
@@ -1,5 +0,0 @@
-Only *code quality* does matter.
-
-Everything else is up to your personal taste.
-
-However, this doesn't mean that we will be tolerant to /any/ kind of antics.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..901239b
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,85 @@
+Please read the following document to make collaborating on the project easier for both sides.
+
+# Reporting bugs
+
+If you've encountered a bug, do the following:
+
+- Check if the documentation has information about the problem you have.
+ Maybe this isn't a bug, but a desired behavior.
+- Check issue tracker, maybe someone had reported your problem already.
+ If there's no issue, describing your problem, or there is, but it is closed, please create new issue, and link all closed issues that relate to this problem, if any.
+- Tag issue with a `BUG:` at the beginning of the issue name.
+
+# Suggesting features and/or changes
+
+Before suggesting a feature, please check if this feature wasn't requested before.
+You can do that in the issues, by filtering issues by `FEATURE:`.
+If no feature found, please file new issue, and tag it with a `FEATURE:` at the beginning of the issue name.
+
+# Contributing changes
+
+Please do.
+
+When deciding to contribute a large amount of changes, first consider opening a `DISCUSSION:` type issue, so we could first decide if such dramatic changes are in the scope of the project.
+This will save your time, in case such changes are out of the project's scope.
+
+If you're contributing a bug-fix, please open a `BUG:` labeled issue first, unless someone already did that.
+All bug related merge requests must have a linked issues with a meaningful explanation and steps of reproducing a bug.
+Small fixes are also welcome, and doesn't require filing an issue, although you may be asked to do so.
+
+## Writing code
+
+When writing code, consider following the existing style without applying dramatic changes to formatting unless really necessary.
+For this particular project, please follow rules as described in [Clojure Style Guide](https://github.com/bbatsov/clojure-style-guide).
+If you see any inconsistencies with the style guide in the code, feel free to change these in a non-breaking way.
+If you're using Emacs, some indentation rules are predefined in `.dir-locals.el` file, so when adding new macro please add a meaningful indentation spec to that file as well.
+
+If you've added new functions, each must be covered with a set of tests.
+For that purpose this project has special `test.fnl` module, that defines such macros as `assert-is`, `assert-not`, `assert-eq`, `assert-ne`, `deftest`, and `testing`.
+Related tests should be grouped with the `deftest` macro, which defines a meaningful name for the test, and test itself must be defined within `testing` macros.
+All assertions in tests must be one with one of `assert-eq`, `assert-ne`, `assert-not`, or `assert-is` macros, as these provide human readable output in the log.
+
+When changing existing functions make sure that all tests pass.
+If some tests do not pass, make sure that these tests are written to test this particular function.
+If the breakage was expected (e.g. when contributing a breaking change), make sure to update the tests.
+If neither from above applies, then, perhaps, you've broke something horribly.
+
+Before committing changes you must run tests with `make test`, and all of the tests must pass without errors.
+Consider checking test coverage with `make luacov` and rendering it with your preferred reporter.
+Makefile also has `luacov-console` target, which can be used to see coverage of Lua code directly in the terminal with [luacov-console](https://github.com/spacewander/luacov-console).
+Coverage should not drop too much, and huge drops usually mean that tests should cover more input variants.
+
+## Writing documentation
+
+If you've added new code, make sure it is covered not only by tests but also with documentation.
+This includes writing documentation strings directly in the code, by using docstring feature of the language.
+Documentation files are auto-generated with [Fenneldoc](https://gitlab.com/andreyorst/fenneldoc), so please refer to its documentation for available features.
+
+General notes on writing documentation:
+
+- Please consider using spell checking.
+ If you find a word not known by the dictionary, please add it to the `LocalWords` section at the bottom of the document.
+- If you're writing markdown by hand, please consider using one sentence per line approach.
+ This makes it easier to reason about text in patches, and Markdown ignores single newlines in sentences.
+- If you're writing documentation for function, consider splitting lines at column 80.
+
+## Working with Git
+
+Check out new branch from project's main development branch.
+If you've cloned this project some time ago, consider checking if your branch has all recent changes from upstream.
+
+Each commit must have a type, which is one of `feature`, `fix`, followed by optional scope, and a must have description after `:` colon.
+For example:
+
+ fix(core macros): fix #42
+ feature(tests): add more strict tests
+
+- `feature` must be used when adding new code.
+- `fix` must be used when working with existing code.
+
+When creating merge request consider squashing your commits at merge.
+You may do this manually, or use Gitlab's "Squash commits" button.
+Either way please tag squash commit with `fix` or `feature`, depending on what you're willing to merge.
+
+<!-- LocalWords: Makefile Gitlab's Lua docstring
+ -->
diff --git a/CONTRIBUTING.org b/CONTRIBUTING.org
deleted file mode 100644
index 9acb924..0000000
--- a/CONTRIBUTING.org
+++ /dev/null
@@ -1,94 +0,0 @@
-#+title: Contributing guidelines
-#+author: Andrey Orst
-#+email: andreyorst@gmail.com
-#+date: 2020-10-24
-
-Please read the following document to make collaborating on the project easier for both sides.
-
-* Reporting bugs
-If you've encountered a bug, do the following:
-
-- Check if the documentation has information about the problem you have.
- Maybe this isn't a bug, but a desired behavior.
-- Check past and current issues, maybe someone had reported your problem already.
- If there's no issue, describing your problem, or there is, but it is closed, please create new issue, and link all closed issues that relate to this problem, if any.
-- Tag issue with a =BUG:= at the beginning of the issue name.
-
-
-* Suggesting features and/or changes
-Before suggesting a feature, please check if this feature wasn't requested before.
-You can do that in the issues, by filtering issues by =FEATURE:=.
-If no feature found, please file new issue, and tag it with a =FEATURE:= at the beginning of the issue name.
-
-
-* Contributing changes
-Please do.
-
-When deciding to contribute a large amount of changes, first consider opening a =DISCUSSION:= type issue, so we could first decide if such dramatic changes are in the scope of the project.
-This will save your time, in case such changes are out of the project's scope.
-
-If you're contributing a bugfix, please open an =BUG:= issue first, unless someone already did that.
-All bug related merge requests must have a linked issues with a meaningful explanation and steps of reproducing a bug.
-Small fixes are also welcome, and doesn't require filing an issue, although we may ask you to do so.
-
-** Writing code
-When writing code, consider following the existing style without applying dramatic changes to formatting unless really necessary.
-For this particular project, please follow rules as described in [[https://github.com/bbatsov/clojure-style-guide][Clojure Style Guide]].
-If you see any inconsistencies with the style guide in the code, feel free to change these in a non-breaking way.
-
-If you've added new functions, each one must be covered with a set of tests.
-For that purpose this project has special =test.fnl= module, that defines such macros as =assert-is=, =assert-not=, =assert-eq=, =assert-ne=, =deftest=, and =testing=.
-Related tests should be grouped with the =deftest= macro, which defines a meaningful name for the test, and test itself must be defined within =testing= macros.
-All assertions in tests must be one with one of =assert-eq=, =assert-ne=, =assert-not=, or =assert-is= macros, as these provide human readable output in the log.
-
-When changing existing functions make sure that all tests pass.
-If some tests do not pass, make sure that these tests are written to test this function.
-If not, then, perhaps, you've broke something horribly.
-
-Before comitting changes you must run tests with =make test=, and all of the tests must pass without errors.
-Consider checking test coverage with =make luacov= and rendering it with your preferred reporter.
-Makefile also has =luacov-console= target, which can be used to see coverage of lua code directly in the terminal with [[https://github.com/spacewander/luacov-console][luacov-console]].
-
-** Writing documentation
-If you've added new code, make sure it is covered not only by tests but also with documentation.
-This includes writing documentation strings directly in the code, either by using docstring feature of the language, or by adding comments which begin with =DOC:=
-
-Documentation files use Org Mode format because it is easy to convert it to all kinds of formats.
-Please make sure to follow existing style of documentation, which can be shortly describing as:
-
-- One sentence per line.
- This makes easier to see changes while browsing history.
-- No indentation of text after headings.
- This makes little sense with one sentence per line approach anyway.
-- No empty lines after headings.
-- Amount of empty lines in text should be:
- - Single empty lines between paragraphs.
- - Double empty lines before top level headings.
- - Single empty lines before other headings.
-- Consider using spell checking.
- If you find a word not known by the dictionary, please add it to the =LocalWords= section at the bottom of the document.
-
-If you're not using Emacs, there are plugins for other editors of varying completeness that provide support for Org file formats.
-Here are some popular ones: Atom [[https://atom.io/packages/org-mode][package]], VSCode [[https://github.com/vscode-org-mode/vscode-org-mode][plugin]], SublimeText [[https://packagecontrol.io/packages/orgmode][plugin]].
-Even without the plugin it is not hard to edit such Org files, as it is just plain text.
-
-** Working with Git
-Check out new branch from project's main development branch.
-If you've cloned this project some time ago, consider checking if your branch has all recent changes from upstream.
-
-Each commit must have a type, which is one of =feature=, =fix=, followed by optional scope, and a must have description after =:= colon.
-For example:
-
-#+begin_example
-fix(core macros): fix #42
-feature(tests): add more strict tests
-#+end_example
-
-- =feature= must be used when adding new code.
-- =fix= must be used when fixing existing code.
-
-When creating merge request consider squashing your commits at merge.
-You may do this manually, or use Gitlab's "Squash commits" button.
-
-# LocalWords: bugfix docstring comitting VSCode SublimeText
-# LocalWords: Gitlab's LocalWords
diff --git a/Makefile b/Makefile
index 6a313b8..83f78f7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,12 @@
LUA ?= lua
FENNEL ?= fennel
-FNLSOURCES = cljlib.fnl
+FNLSOURCES = init.fnl
LUASOURCES = $(FNLSOURCES:.fnl=.lua)
FNLTESTS = tests/fn.fnl tests/macros.fnl tests/core.fnl
LUATESTS = $(FNLTESTS:.fnl=.lua)
+LUA_EXECUTABLES ?= lua luajit
-.PHONY: build clean distclean help test luacov luacov-console fenneldoc
+.PHONY: build clean distclean help test luacov luacov-console fenneldoc $(LUA_EXECUTABLES)
build: $(LUASOURCES)
@@ -21,10 +22,14 @@ distclean: clean
rm -f luacov*
test: $(FNLTESTS)
- @true$(foreach test, $?, && $(FENNEL) --lua $(LUA) --metadata $(test))
+ @echo "Testing on" $$($(LUA) -v) >&2
+ @$(foreach test,$?,$(FENNEL) --lua $(LUA) --metadata $(test) || exit;)
+
+testall: $(LUA_EXECUTABLES)
+ @$(foreach lua,$?,LUA=$(lua) make test || exit;)
luacov: build $(LUATESTS)
- @true$(foreach test, $(LUATESTS), && $(LUA) -lluarocks.loader -lluacov $(test))
+ @$(foreach test,$(LUATESTS),$(LUA) -lluarocks.loader -lluacov $(test) || exit;)
luacov
luacov-console: luacov
@@ -33,7 +38,7 @@ luacov-console: luacov
@$(foreach test, $(LUATESTS), mv $(test).tmp $(test);)
fenneldoc:
- fenneldoc cljlib.fnl cljlib-macros.fnl tests/test.fnl
+ fenneldoc init.fnl macros.fnl tests/test.fnl
help:
@echo "make -- run tests and create lua library" >&2
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6b213a5
--- /dev/null
+++ b/README.md
@@ -0,0 +1,40 @@
+# Fennel Cljlib
+
+[![img](https://gitlab.com/andreyorst/fennel-cljlib/badges/master/pipeline.svg)](https://gitlab.com/andreyorst/fennel-cljlib/-/commits/master)
+[![img](https://gitlab.com/andreyorst/fennel-cljlib/badges/master/coverage.svg)](https://gitlab.com/andreyorst/fennel-cljlib/-/commits/master)
+
+Experimental library for [Fennel](https://fennel-lang.org/) language, that adds many functions from [Clojure](https://clojure.org/)'s standard library.
+This is not a one to one port of Clojure `core`, because many Clojure functions require certain guarantees, like immutability and laziness, which are hard to efficiently implement on top of Lua.
+Some semantics like concurrency, or dynamic scope is not supported by Lua runtime at all.
+Therefore certain functions were altered to better suit the domain.
+
+## Installation
+
+Clone library into your project or put it as a git submodule:
+
+ $ git clone https://gitlab.com/andreyorst/fennel-cljlib cljlib
+
+Now you can require `:cljlib` from Fennel:
+
+``` clojure
+(local clj (require :cljlib))
+(import-macros cljm :cljlib.macros)
+```
+
+Optionally precompile the library to make it load slightly faster:
+
+ $ cd cljlib; make
+
+This will compile `init.fnl` into `init.lua`, so `require` should honor Lua files over Fennel files.
+It is also possible to use this library from Lua this way.
+
+## Documentation
+
+Documentation is auto-generated with [Fenneldoc](https://gitlab.com/andreyorst/fenneldoc) and can be found [here](https://gitlab.com/andreyorst/fennel-cljlib/-/tree/master/doc).
+
+# Contributing
+
+Please make sure you've read [contribution guidelines](https://gitlab.com/andreyorst/fennel-cljlib/-/tree/master/CONTRIBUTING.md).
+
+<!-- LocalWords: Lua submodule precompile cljlib
+ -->
diff --git a/README.org b/README.org
deleted file mode 100644
index e30d62c..0000000
--- a/README.org
+++ /dev/null
@@ -1,14 +0,0 @@
-#+title: Fennel Cljlib
-[[https://gitlab.com/andreyorst/fennel-cljlib/-/commits/master][https://gitlab.com/andreyorst/fennel-cljlib/badges/master/pipeline.svg]] [[https://gitlab.com/andreyorst/fennel-cljlib/-/commits/master][https://gitlab.com/andreyorst/fennel-cljlib/badges/master/coverage.svg]]
-
-Experimental library for [[https://fennel-lang.org/][Fennel]] language, that adds many functions from [[https://clojure.org/][Clojure]]'s standard library.
-This is not a one to one port of Clojure =core=, because many Clojure functions require certain guarantees, like immutability of the underlying data structures, or laziness.
-Therefore some names were changed, but they should be still recognizable, and certain functions were altered to better suit the domain.
-
-Even though it is project is experimental, the goals of this project are:
-
-- Have a self contained library, with no dependencies, that provides a set of useful functions from Clojure =core=,
-- Be close to the platform, e.g. implement functions in a way that is efficient to use in Lua VM,
-- Be well documented library, with good test coverage.
-
-Documentation is autogenerated with [[https://gitlab.com/andreyorst/fenneldoc][Fenneldoc]] and can be found [[https://gitlab.com/andreyorst/fennel-cljlib/-/tree/master/doc][here]].
diff --git a/doc/cljlib.md b/doc/cljlib.md
index ee686cf..54d8294 100644
--- a/doc/cljlib.md
+++ b/doc/cljlib.md
@@ -1,10 +1,10 @@
-# Cljlib.fnl (0.3.0)
+# Cljlib (0.4.0)
Fennel-cljlib - functions from Clojure's core.clj implemented on top
of Fennel.
This library contains a set of functions providing functions that
behave similarly to Clojure's equivalents. Library itself has nothing
-Fennel specific so it should work, e.g:
+Fennel specific so it should work on Lua, e.g:
``` lua
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
@@ -35,6 +35,17 @@ of a function which is chosen by checking amount of arguments passed
to the function. See [Clojure's doc section on multi-arity
functions](https://clojure.org/guides/learn/functions#_multi_arity_functions).
+## Compatibility
+This library is mainly developed with Lua 5.4, and tested against
+Lua 5.2, 5.3, 5.4, and LuaJIT 2.1.0-beta3. Note, that in lua 5.2 and
+LuaJIT equality semantics are a bit different from Lua 5.3 and Lua 5.4.
+Main difference is that when comparing two tables, they must have
+exactly the same `__eq` metamethods, so comparing hash sets with hash
+sets will work, but comparing sets with other tables works only in
+Lua5.3+. Another difference is that Lua 5.2 and LuaJIT don't have
+inbuilt UTF-8 library, therefore `seq` function will not work for
+non-ASCII strings.
+
**Table of contents**
- [`apply`](#apply)
@@ -142,12 +153,7 @@ Applying `print` to different arguments:
Function signature:
```
-(add
- ([a])
- ([a b])
- ([a b c])
- ([a b c d])
- ([a b c d & rest]))
+(add ([]) ([a]) ([a b]) ([a b c]) ([a b c d]) ([a b c d & rest]))
```
Sum arbitrary amount of numbers.
@@ -156,12 +162,7 @@ Sum arbitrary amount of numbers.
Function signature:
```
-(sub
- ([a])
- ([a b])
- ([a b c])
- ([a b c d])
- ([a b c d & rest]))
+(sub ([]) ([a]) ([a b]) ([a b c]) ([a b c d]) ([a b c d & rest]))
```
Subtract arbitrary amount of numbers.
@@ -170,12 +171,7 @@ Subtract arbitrary amount of numbers.
Function signature:
```
-(mul
- ([a])
- ([a b])
- ([a b c])
- ([a b c d])
- ([a b c d & rest]))
+(mul ([]) ([a]) ([a b]) ([a b c]) ([a b c d]) ([a b c d & rest]))
```
Multiply arbitrary amount of numbers.
@@ -184,12 +180,7 @@ Multiply arbitrary amount of numbers.
Function signature:
```
-(div
- ([a])
- ([a b])
- ([a b c])
- ([a b c d])
- ([a b c d & rest]))
+(div ([a]) ([a b]) ([a b c]) ([a b c d]) ([a b c d & rest]))
```
Divide arbitrary amount of numbers.
@@ -198,10 +189,7 @@ Divide arbitrary amount of numbers.
Function signature:
```
-(le
- ([x])
- ([x y])
- ([x y & more]))
+(le ([x]) ([x y]) ([x y & more]))
```
Returns true if nums are in monotonically non-decreasing order
@@ -210,10 +198,7 @@ Returns true if nums are in monotonically non-decreasing order
Function signature:
```
-(lt
- ([x])
- ([x y])
- ([x y & more]))
+(lt ([x]) ([x y]) ([x y & more]))
```
Returns true if nums are in monotonically decreasing order
@@ -222,10 +207,7 @@ Returns true if nums are in monotonically decreasing order
Function signature:
```
-(ge
- ([x])
- ([x y])
- ([x y & more]))
+(ge ([x]) ([x y]) ([x y & more]))
```
Returns true if nums are in monotonically non-increasing order
@@ -234,10 +216,7 @@ Returns true if nums are in monotonically non-increasing order
Function signature:
```
-(gt
- ([x])
- ([x y])
- ([x y & more]))
+(gt ([x]) ([x y]) ([x y & more]))
```
Returns true if nums are in monotonically increasing order
@@ -246,7 +225,7 @@ Returns true if nums are in monotonically increasing order
Function signature:
```
-(inc [x])
+(inc ([x]))
```
Increase number by one
@@ -255,7 +234,7 @@ Increase number by one
Function signature:
```
-(dec [x])
+(dec ([x]))
```
Decrease number by one
@@ -264,10 +243,7 @@ Decrease number by one
Function signature:
```
-(eq
- ([x])
- ([x y])
- ([x y & xs]))
+(eq ([x]) ([x y]) ([x y & xs]))
```
Deep compare values.
@@ -276,7 +252,7 @@ Deep compare values.
Function signature:
```
-(map? [tbl])
+(map? ([tbl]))
```
Check whether `tbl` is an associative table.
@@ -318,7 +294,7 @@ Empty tables created with [`hash-map`](#hash-map) will pass the test:
Function signature:
```
-(vector? [tbl])
+(vector? ([tbl]))
```
Check whether `tbl` is an sequential table.
@@ -360,7 +336,7 @@ Empty tables created with [`vector`](#vector) will pass the test:
Function signature:
```
-(multifn? [mf])
+(multifn? ([mf]))
```
Test if `mf` is an instance of `multifn`.
@@ -372,7 +348,7 @@ from `cljlib-macros.fnl`.
Function signature:
```
-(set? [s])
+(set? ([s]))
```
@@ -381,8 +357,7 @@ Function signature:
Function signature:
```
-(nil?
- ([x]))
+(nil? ([]) ([x]))
```
Test if value is nil.
@@ -391,7 +366,7 @@ Test if value is nil.
Function signature:
```
-(zero? [x])
+(zero? ([x]))
```
Test if value is equal to zero.
@@ -400,7 +375,7 @@ Test if value is equal to zero.
Function signature:
```
-(pos? [x])
+(pos? ([x]))
```
Test if `x` is greater than zero.
@@ -409,7 +384,7 @@ Test if `x` is greater than zero.
Function signature:
```
-(neg? [x])
+(neg? ([x]))
```
Test if `x` is less than zero.
@@ -418,7 +393,7 @@ Test if `x` is less than zero.
Function signature:
```
-(even? [x])
+(even? ([x]))
```
Test if value is even.
@@ -427,7 +402,7 @@ Test if value is even.
Function signature:
```
-(odd? [x])
+(odd? ([x]))
```
Test if value is odd.
@@ -436,7 +411,7 @@ Test if value is odd.
Function signature:
```
-(string? [x])
+(string? ([x]))
```
Test if `x` is a string.
@@ -445,7 +420,7 @@ Test if `x` is a string.
Function signature:
```
-(boolean? [x])
+(boolean? ([x]))
```
Test if `x` is a Boolean
@@ -454,7 +429,7 @@ Test if `x` is a Boolean
Function signature:
```
-(true? [x])
+(true? ([x]))
```
Test if `x` is `true`
@@ -463,7 +438,7 @@ Test if `x` is `true`
Function signature:
```
-(false? [x])
+(false? ([x]))
```
Test if `x` is `false`
@@ -472,7 +447,7 @@ Test if `x` is `false`
Function signature:
```
-(int? [x])
+(int? ([x]))
```
Test if `x` is a number without floating point data.
@@ -483,7 +458,7 @@ Number is rounded with `math.floor` and compared with original number.
Function signature:
```
-(pos-int? [x])
+(pos-int? ([x]))
```
Test if `x` is a positive integer.
@@ -492,16 +467,16 @@ Test if `x` is a positive integer.
Function signature:
```
-(neg-int? [x])
+(neg-int? ([x]))
```
-Test if `x` is a negetive integer.
+Test if `x` is a negative integer.
## `double?`
Function signature:
```
-(double? [x])
+(double? ([x]))
```
Test if `x` is a number with floating point data.
@@ -510,7 +485,7 @@ Test if `x` is a number with floating point data.
Function signature:
```
-(empty? [x])
+(empty? ([x]))
```
Check if collection is empty.
@@ -519,7 +494,7 @@ Check if collection is empty.
Function signature:
```
-(not-empty [x])
+(not-empty ([x]))
```
If `x` is empty, returns `nil`, otherwise `x`.
@@ -528,7 +503,7 @@ If `x` is empty, returns `nil`, otherwise `x`.
Function signature:
```
-(vector [& args])
+(vector ([& args]))
```
Constructs sequential table out of it's arguments.
@@ -546,7 +521,7 @@ Sets additional metadata for function [`vector?`](#vector?) to work.
Function signature:
```
-(seq [col])
+(seq ([col]))
```
Create sequential table.
@@ -554,7 +529,8 @@ Create sequential table.
Transforms original table to sequential table of key value pairs
stored as sequential tables in linear time. If `col` is an
associative table, returns sequential table of vectors with key and
-value. If `col` is sequential table, returns its shallow copy.
+value. If `col` is sequential table, returns its shallow copy. If
+`col` is string, return sequential table of its codepoints.
### Examples
Sequential tables remain as is:
@@ -585,16 +561,16 @@ Additionally you can use [`conj`](#conj) and [`apply`](#apply) with
Function signature:
```
-(kvseq [tbl])
+(kvseq ([col]))
```
-Transforms any table kind to key-value sequence.
+Transforms any table to key-value sequence.
## `first`
Function signature:
```
-(first [col])
+(first ([col]))
```
Return first element of a table. Calls `seq` on its argument.
@@ -603,7 +579,7 @@ Return first element of a table. Calls `seq` on its argument.
Function signature:
```
-(rest [col])
+(rest ([col]))
```
Returns table of all elements of a table but the first one. Calls
@@ -613,7 +589,7 @@ Returns table of all elements of a table but the first one. Calls
Function signature:
```
-(last [col])
+(last ([col]))
```
Returns the last element of a table. Calls `seq` on its argument.
@@ -622,7 +598,7 @@ Returns the last element of a table. Calls `seq` on its argument.
Function signature:
```
-(butlast [col])
+(butlast ([col]))
```
Returns everything but the last element of a table as a new
@@ -632,10 +608,7 @@ Returns everything but the last element of a table as a new
Function signature:
```
-(conj
- ([tbl])
- ([tbl x])
- ([tbl x & xs]))
+(conj ([]) ([tbl]) ([tbl x]) ([tbl x & xs]))
```
Insert `x` as a last element of a table `tbl`.
@@ -680,10 +653,7 @@ See [`hash-map`](#hash-map) for creating empty associative tables.
Function signature:
```
-(disj
- ([s])
- ([s k])
- ([s k & ks]))
+(disj ([s]) ([s k]) ([s k & ks]))
```
Remove key `k` from set `s`.
@@ -692,7 +662,7 @@ Remove key `k` from set `s`.
Function signature:
```
-(cons [x tbl])
+(cons ([x tbl]))
```
Insert `x` to `tbl` at the front. Calls [`seq`](#seq) on `tbl`.
@@ -701,10 +671,7 @@ Insert `x` to `tbl` at the front. Calls [`seq`](#seq) on `tbl`.
Function signature:
```
-(concat
- ([x])
- ([x y])
- ([x y & xs]))
+(concat ([]) ([x]) ([x y]) ([x y & xs]))
```
Concatenate tables.
@@ -713,9 +680,7 @@ Concatenate tables.
Function signature:
```
-(reduce
- ([f col])
- ([f val col]))
+(reduce ([f col]) ([f val col]))
```
Reduce collection `col` using function `f` and optional initial value `val`.
@@ -747,7 +712,7 @@ Reduce sequence of numbers with [`add`](#add)
Function signature:
```
-(reduced [x])
+(reduced ([x]))
```
Wraps `x` in such a way so [`reduce`](#reduce) will terminate early
@@ -779,7 +744,7 @@ valid number, but we've terminated right before we've reached it.
Function signature:
```
-(reduce-kv [f val tbl])
+(reduce-kv ([f val tbl]))
```
Reduces an associative table using function `f` and initial value `val`.
@@ -869,7 +834,7 @@ Basic `zipmap` implementation:
Function signature:
```
-(filter [pred col])
+(filter ([pred col]))
```
Returns a sequential table of the items in `col` for which `pred`
@@ -879,7 +844,7 @@ Returns a sequential table of the items in `col` for which `pred`
Function signature:
```
-(every? [pred tbl])
+(every? ([pred tbl]))
```
Test if every item in `tbl` satisfies the `pred`.
@@ -888,7 +853,7 @@ Test if every item in `tbl` satisfies the `pred`.
Function signature:
```
-(some [pred tbl])
+(some ([pred tbl]))
```
Test if any item in `tbl` satisfies the `pred`.
@@ -897,7 +862,7 @@ Test if any item in `tbl` satisfies the `pred`.
Function signature:
```
-(not-any? [pred tbl])
+(not-any? ([pred tbl]))
```
Test if no item in `tbl` satisfy the `pred`.
@@ -906,10 +871,7 @@ Test if no item in `tbl` satisfy the `pred`.
Function signature:
```
-(range
- ([upper])
- ([lower upper])
- ([lower upper step]))
+(range ([upper]) ([lower upper]) ([lower upper step]))
```
return range of of numbers from `lower` to `upper` with optional `step`.
@@ -918,7 +880,7 @@ return range of of numbers from `lower` to `upper` with optional `step`.
Function signature:
```
-(reverse [tbl])
+(reverse ([tbl]))
```
Returns table with same items as in `tbl` but in reverse order.
@@ -927,7 +889,7 @@ Returns table with same items as in `tbl` but in reverse order.
Function signature:
```
-(identity [x])
+(identity ([x]))
```
Returns its argument.
@@ -936,10 +898,7 @@ Returns its argument.
Function signature:
```
-(comp
- ([f])
- ([f g])
- ([f g & fs]))
+(comp ([]) ([f]) ([f g]) ([f g & fs]))
```
Compose functions.
@@ -948,7 +907,7 @@ Compose functions.
Function signature:
```
-(complement [f])
+(complement ([f]))
```
Takes a function `f` and returns the function that takes the same
@@ -959,7 +918,7 @@ oppisite truth value.
Function signature:
```
-(constantly [x])
+(constantly ([x]))
```
Returns a function that takes any number of arguments and returns `x`.
@@ -968,7 +927,7 @@ Returns a function that takes any number of arguments and returns `x`.
Function signature:
```
-(memoize [f])
+(memoize ([f]))
```
Returns a memoized version of a referentially transparent function.
@@ -981,9 +940,7 @@ use.
Function signature:
```
-(assoc
- ([tbl k v])
- ([tbl k v & kvs]))
+(assoc ([tbl k v]) ([tbl k v & kvs]))
```
Associate key `k` with value `v` in `tbl`.
@@ -992,8 +949,7 @@ Associate key `k` with value `v` in `tbl`.
Function signature:
```
-(hash-map
- ([& kvs]))
+(hash-map ([]) ([& kvs]))
```
Create associative table from keys and values
@@ -1002,9 +958,7 @@ Create associative table from keys and values
Function signature:
```
-(get
- ([tbl key])
- ([tbl key not-found]))
+(get ([tbl key]) ([tbl key not-found]))
```
Get value from the table by accessing it with a `key`.
@@ -1015,9 +969,7 @@ found in the table.
Function signature:
```
-(get-in
- ([tbl keys])
- ([tbl keys not-found]))
+(get-in ([tbl keys]) ([tbl keys not-found]))
```
Get value from nested set of tables by providing key sequence.
@@ -1028,7 +980,7 @@ found in the table.
Function signature:
```
-(keys [tbl])
+(keys ([tbl]))
```
Returns a sequence of the table's keys, in the same order as [`seq`](#seq).
@@ -1037,7 +989,7 @@ Returns a sequence of the table's keys, in the same order as [`seq`](#seq).
Function signature:
```
-(vals [tbl])
+(vals ([tbl]))
```
Returns a sequence of the table's values, in the same order as [`seq`](#seq).
@@ -1046,7 +998,7 @@ Returns a sequence of the table's values, in the same order as [`seq`](#seq).
Function signature:
```
-(find [tbl key])
+(find ([tbl key]))
```
Returns the map entry for `key`, or `nil` if key not present.
@@ -1055,10 +1007,7 @@ Returns the map entry for `key`, or `nil` if key not present.
Function signature:
```
-(dissoc
- ([tbl])
- ([tbl key])
- ([tbl key & keys]))
+(dissoc ([tbl]) ([tbl key]) ([tbl key & keys]))
```
Remove `key` from table `tbl`.
@@ -1067,7 +1016,7 @@ Remove `key` from table `tbl`.
Function signature:
```
-(remove-method [multifn dispatch-val])
+(remove-method ([multifn dispatch-val]))
```
Remove method from `multifn` for given `dispatch-val`.
@@ -1076,7 +1025,7 @@ Remove method from `multifn` for given `dispatch-val`.
Function signature:
```
-(remove-all-methods [multifn])
+(remove-all-methods ([multifn]))
```
Removes all of the methods of multimethod
@@ -1085,7 +1034,7 @@ Removes all of the methods of multimethod
Function signature:
```
-(methods [multifn])
+(methods ([multifn]))
```
Given a multimethod, returns a map of dispatch values -> dispatch fns
@@ -1094,7 +1043,7 @@ Given a multimethod, returns a map of dispatch values -> dispatch fns
Function signature:
```
-(get-method [multifn dispatch-val])
+(get-method ([multifn dispatch-val]))
```
Given a multimethod and a dispatch value, returns the dispatch `fn`
@@ -1104,7 +1053,7 @@ that would apply to that value, or `nil` if none apply and no default.
Function signature:
```
-(ordered-set [& xs])
+(ordered-set ([& xs]))
```
Create ordered set.
@@ -1118,7 +1067,7 @@ at the end of the set. Ordered set supports removal of items via
`tset` and [`disj`](#disj). To add element to the ordered set use
`tset` or [`conj`](#conj). Both operations modify the set.
-**Note**: Hash set prints as `#{a b c}`, but this construct is not
+**Note**: Hash set prints as `@set{a b c}`, but this construct is not
supported by the Fennel reader, so you can't create sets with this
syntax. Use `hash-set` function instead.
@@ -1130,18 +1079,16 @@ be in the set:
``` fennel
>> (ordered-set)
-#{}
+@set{}
>> (ordered-set :a :c :b)
-#{"a" "c" "b"}
+@set{:a :c :b}
```
Duplicate items are not added:
``` fennel
->> (ordered-set)
-#{}
>> (ordered-set :a :c :a :a :a :a :c :b)
-#{"a" "c" "b"}
+@set{:a :c :b}
```
#### Check if set contains desired value:
@@ -1151,9 +1098,9 @@ desired key will either return the key, or `nil`:
``` fennel
>> (local oset (ordered-set [:a :b :c] [:c :d :e] :e :f))
>> (oset [:a :b :c])
-[:a :b :c]
+["a" "b" "c"]
>> (. oset :e)
-:e
+"e"
>> (oset [:a :b :f])
nil
```
@@ -1164,8 +1111,7 @@ To add element to the set use [`conj`](#conj) or `tset`
``` fennel
>> (local oset (ordered-set :a :b :c))
>> (conj oset :d :e)
->> oset
-#{"a" "b" "c" "d" "e"}
+@set{:a :b :c :d :e}
```
##### Remove items from the set:
@@ -1174,11 +1120,10 @@ To add element to the set use [`disj`](#disj) or `tset`
``` fennel
>> (local oset (ordered-set :a :b :c))
>> (disj oset :b)
->> oset
-#{"a" "c"}
+@set{:a :c}
>> (tset oset :a nil)
>> oset
-#{"c"}
+@set{:c}
```
#### Equality semantics
@@ -1199,7 +1144,7 @@ true
Function signature:
```
-(hash-set [& xs])
+(hash-set ([& xs]))
```
Create hash set.
@@ -1213,7 +1158,7 @@ using [`conj`](#con) or `tset` functions, and items can be removed
with [`disj`](#disj) or `tset` functions. Rest semantics are the same
as for [`ordered-set`](#ordered-set)
-**Note**: Hash set prints as `#{a b c}`, but this construct is not
+**Note**: Hash set prints as `@set{a b c}`, but this construct is not
supported by the Fennel reader, so you can't create sets with this
syntax. Use `hash-set` function instead.
@@ -1225,5 +1170,5 @@ Copyright (C) 2020 Andrey Orst
License: [MIT](https://gitlab.com/andreyorst/fennel-cljlib/-/raw/master/LICENSE)
-<!-- Generated with Fenneldoc 0.0.6
+<!-- Generated with Fenneldoc 0.0.7
https://gitlab.com/andreyorst/fenneldoc -->
diff --git a/doc/cljlib-macros.md b/doc/macros.md
index a29fb0f..e9cc517 100644
--- a/doc/cljlib-macros.md
+++ b/doc/macros.md
@@ -1,4 +1,4 @@
-# Cljlib-macros.fnl (0.3.0)
+# Macros.fnl (0.3.0)
Macros for Cljlib that implement various facilities from Clojure.
**Table of contents**
@@ -18,6 +18,7 @@ Macros for Cljlib that implement various facilities from Clojure.
- [`when-let`](#when-let)
- [`if-some`](#if-some)
- [`when-some`](#when-some)
+- [`deep-tostring`](#deep-tostring)
## `fn*`
Function signature:
@@ -27,7 +28,7 @@ Function signature:
```
Create (anonymous) function of fixed arity.
-Supports multiple arities by defining bodies as lists:
+Supports multiple arities by defining bodies as lists.
### Examples
Named function of fixed arity 2:
@@ -158,18 +159,15 @@ Function signature:
```
General purpose try/catch/finally macro.
-
-(try expression* catch-clause* finally-clause?)
-
Wraps its body in `pcall` and checks the return value with `match`
macro.
-Catch-clause is written either as (catch symbol body*), thus acting as
+Catch clause is written either as (catch symbol body*), thus acting as
catch-all, or (catch value body*) for catching specific errors. It is
possible to have several `catch` clauses. If no `catch` clauses
specified, an implicit catch-all clause is created.
-Finally-clause is optional, and written as (finally body*). If
+Finally clause is optional, and written as (finally body*). If
present, it must be the last clause in the `try` form, and the only
`finally` clause. Note that `finally` clause is for side effects
only, and runs either after succesful run of `try` body, or after any
@@ -569,6 +567,15 @@ Function signature:
If test is non-`nil`,
evaluates `body` in implicit `do`.
+## `deep-tostring`
+Function signature:
+
+```
+(deep-tostring data key?)
+```
+
+**Undocumented**
+
---
@@ -577,5 +584,5 @@ Copyright (C) 2020 Andrey Orst
License: [MIT](https://gitlab.com/andreyorst/fennel-cljlib/-/raw/master/LICENSE)
-<!-- Generated with Fenneldoc 0.0.6
+<!-- Generated with Fenneldoc 0.0.7
https://gitlab.com/andreyorst/fenneldoc -->
diff --git a/doc/tests/test.md b/doc/tests/test.md
index c338561..8a6c7e5 100644
--- a/doc/tests/test.md
+++ b/doc/tests/test.md
@@ -94,5 +94,5 @@ Function signature:
Assert for not truth. Works the same as [`assert-is`](#assert-is).
-<!-- Generated with Fenneldoc 0.0.6
+<!-- Generated with Fenneldoc 0.0.7
https://gitlab.com/andreyorst/fenneldoc -->
diff --git a/cljlib.fnl b/init.fnl
index 5820d57..623120d 100644
--- a/cljlib.fnl
+++ b/init.fnl
@@ -1,12 +1,13 @@
-(local core {:_VERSION "0.3.0"
+(local core {:_VERSION "0.4.0"
:_LICENSE "[MIT](https://gitlab.com/andreyorst/fennel-cljlib/-/raw/master/LICENSE)"
:_COPYRIGHT "Copyright (C) 2020 Andrey Orst"
+ :_MODULE_NAME "cljlib"
:_DESCRIPTION "Fennel-cljlib - functions from Clojure's core.clj implemented on top
of Fennel.
This library contains a set of functions providing functions that
behave similarly to Clojure's equivalents. Library itself has nothing
-Fennel specific so it should work, e.g:
+Fennel specific so it should work on Lua, e.g:
``` lua
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
@@ -35,11 +36,24 @@ zs]))`, it is a multi-arity function, which accepts either one, two,
or three-or-more arguments. Each `([...])` represents different body
of a function which is chosen by checking amount of arguments passed
to the function. See [Clojure's doc section on multi-arity
-functions](https://clojure.org/guides/learn/functions#_multi_arity_functions)."})
+functions](https://clojure.org/guides/learn/functions#_multi_arity_functions).
+
+## Compatibility
+This library is mainly developed with Lua 5.4, and tested against
+Lua 5.2, 5.3, 5.4, and LuaJIT 2.1.0-beta3. Note, that in lua 5.2 and
+LuaJIT equality semantics are a bit different from Lua 5.3 and Lua 5.4.
+Main difference is that when comparing two tables, they must have
+exactly the same `__eq` metamethods, so comparing hash sets with hash
+sets will work, but comparing sets with other tables works only in
+Lua5.3+. Another difference is that Lua 5.2 and LuaJIT don't have
+inbuilt UTF-8 library, therefore `seq` function will not work for
+non-ASCII strings."})
(local insert table.insert)
(local _unpack (or table.unpack _G.unpack))
-(require-macros :cljlib-macros)
+(import-macros {: fn* : into : empty : with-meta
+ : when-let : if-let : when-some : if-some}
+ (.. (if (and ... (not= ... :init)) (.. ... ".") "") :macros))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Utility functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -331,7 +345,7 @@ Number is rounded with `math.floor` and compared with original number."
(pos? x)))
(fn* core.neg-int?
- "Test if `x` is a negetive integer."
+ "Test if `x` is a negative integer."
[x]
(and (int? x)
(neg? x)))
@@ -362,7 +376,7 @@ Number is rounded with `math.floor` and compared with original number."
:int? :pos-int? :neg-int? :double? :empty? :not-empty])
-;;;;;;;;;;;;;;;;;;;;;; Sequence manipuletion functions ;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;; Sequence manipulation functions ;;;;;;;;;;;;;;;;;;;;;;;;;
(fn* core.vector
"Constructs sequential table out of it's arguments.
@@ -384,7 +398,8 @@ Sets additional metadata for function [`vector?`](#vector?) to work.
Transforms original table to sequential table of key value pairs
stored as sequential tables in linear time. If `col` is an
associative table, returns sequential table of vectors with key and
-value. If `col` is sequential table, returns its shallow copy.
+value. If `col` is sequential table, returns its shallow copy. If
+`col` is string, return sequential table of its codepoints.
# Examples
Sequential tables remain as is:
@@ -424,20 +439,41 @@ Additionally you can use [`conj`](#conj) and [`apply`](#apply) with
(insert res v)
(insert assoc-res [k v]))
(if assoc? assoc-res res))))
- :string (let [char utf8.char]
- (each [_ b (utf8.codes col)]
- (insert res (char b)))
- res)
+ :string (if _G.utf8
+ (let [char _G.utf8.char]
+ (each [_ b (_G.utf8.codes col)]
+ (insert res (char b)))
+ res)
+ (do (io.stderr:write
+ "WARNING: utf8 module unavailable, seq function will not work for non-unicode strings\n")
+ (each [b (col:gmatch ".")]
+ (insert res b))
+ res))
:nil nil
- _ (error (.. "expected table, string or nil") 2))))
+ _ (error (.. "expected table, string or nil, got " (type col)) 2))))
(fn* core.kvseq
- "Transforms any table kind to key-value sequence."
- [tbl]
+ "Transforms any table to key-value sequence."
+ [col]
(let [res (empty [])]
- (each [k v (pairs tbl)]
- (insert res [k v]))
- res))
+ (match (type col)
+ :table (let [m (or (getmetatable col) {})]
+ (when-some [_ ((or m.cljlib/next next) col)]
+ (each [k v (pairs col)]
+ (insert res [k v]))
+ res))
+ :string (if _G.utf8
+ (let [char _G.utf8.char]
+ (each [i b (_G.utf8.codes col)]
+ (insert res [i (char b)]))
+ res)
+ (do (io.stderr:write
+ "WARNING: utf8 module unavailable, seq function will not work for non-unicode strings\n")
+ (for [i 1 (length col)]
+ (insert res [i (col:sub i i)]))
+ res))
+ :nil nil
+ _ (error (.. "expected table, string or nil, got " (type col)) 2))))
(fn* core.first
"Return first element of a table. Calls `seq` on its argument."
@@ -518,8 +554,6 @@ See [`hash-map`](#hash-map) for creating empty associative tables."
(let [tbl (or tbl (empty []))]
(if (map? tbl)
(tset tbl (. x 1) (. x 2))
- (set? tbl)
- (tset tbl x x)
(insert tbl x))))
tbl)
([tbl x & xs]
@@ -895,7 +929,7 @@ oppisite truth value."
(fn* core.constantly
"Returns a function that takes any number of arguments and returns `x`."
[x]
- (fn [...] x))
+ (fn [] x))
(fn* core.memoize
"Returns a memoized version of a referentially transparent function.
@@ -1048,12 +1082,21 @@ that would apply to that value, or `nil` if none apply and no default."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Sets ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(fn viewset [Set]
- "Workaround for a bug https://todo.sr.ht/~technomancy/fennel/26"
- (let [items []]
- (each [_ v (pairs Set)]
- (insert items ((require :fennelview) v)))
- (.. "#{" (table.concat items " ") "}")))
+(fn viewset [Set view inspector indent]
+ (if (. inspector.seen Set)
+ (.. "@set" (. inspector.seen Set) "{...}")
+ (let [prefix (.. "@set"
+ (if (inspector.visible-cycle? Set)
+ (. inspector.seen Set) "")
+ "{")
+ set-indent (length prefix)
+ indent-str (string.rep " " set-indent)
+ lines (icollect [i v (pairs Set)]
+ (.. (if (= i 1) "" indent-str)
+ (view v inspector (+ indent set-indent) true)))]
+ (tset lines 1 (.. prefix (or (. lines 1) "")))
+ (tset lines (length lines) (.. (. lines (length lines)) "}"))
+ (values lines (> (length lines) inspector.sequential-length)))))
(fn ordered-set-newindex [Set]
"`__newindex` metamethod for ordered-set."
@@ -1118,6 +1161,12 @@ that would apply to that value, or `nil` if none apply and no default."
(values i k))))
(values iter Set nil)))
+(fn into-set [Set tbl]
+ "Transform `tbl` into `Set`"
+ (each [_ v (pairs (or (seq tbl) []))]
+ (conj Set v))
+ Set)
+
;; Sets are bootstrapped upon previous functions.
(fn* core.ordered-set
@@ -1132,7 +1181,7 @@ at the end of the set. Ordered set supports removal of items via
`tset` and [`disj`](#disj). To add element to the ordered set use
`tset` or [`conj`](#conj). Both operations modify the set.
-**Note**: Hash set prints as `#{a b c}`, but this construct is not
+**Note**: Hash set prints as `@set{a b c}`, but this construct is not
supported by the Fennel reader, so you can't create sets with this
syntax. Use `hash-set` function instead.
@@ -1144,18 +1193,16 @@ be in the set:
``` fennel
>> (ordered-set)
-#{}
+@set{}
>> (ordered-set :a :c :b)
-#{\"a\" \"c\" \"b\"}
+@set{:a :c :b}
```
Duplicate items are not added:
``` fennel
->> (ordered-set)
-#{}
>> (ordered-set :a :c :a :a :a :a :c :b)
-#{\"a\" \"c\" \"b\"}
+@set{:a :c :b}
```
## Check if set contains desired value:
@@ -1165,9 +1212,9 @@ desired key will either return the key, or `nil`:
``` fennel
>> (local oset (ordered-set [:a :b :c] [:c :d :e] :e :f))
>> (oset [:a :b :c])
-[:a :b :c]
+[\"a\" \"b\" \"c\"]
>> (. oset :e)
-:e
+\"e\"
>> (oset [:a :b :f])
nil
```
@@ -1178,8 +1225,7 @@ To add element to the set use [`conj`](#conj) or `tset`
``` fennel
>> (local oset (ordered-set :a :b :c))
>> (conj oset :d :e)
->> oset
-#{\"a\" \"b\" \"c\" \"d\" \"e\"}
+@set{:a :b :c :d :e}
```
### Remove items from the set:
@@ -1188,11 +1234,10 @@ To add element to the set use [`disj`](#disj) or `tset`
``` fennel
>> (local oset (ordered-set :a :b :c))
>> (disj oset :b)
->> oset
-#{\"a\" \"c\"}
+@set{:a :c}
>> (tset oset :a nil)
>> oset
-#{\"c\"}
+@set{:c}
```
## Equality semantics
@@ -1219,12 +1264,12 @@ true
(setmetatable {}
{:cljlib/type :cljlib/ordered-set
:cljlib/next #(next Set $2)
+ :cljlib/into into-set
+ :cljlib/empty #(ordered-set)
:__eq set-eq
- :__call #(if (. Set $2) $2)
+ :__call #(if (. Set $2) $2 nil)
:__len (set-length Set)
- :__index #(match $2
- :cljlib/empty #(ordered-set)
- _ (if (. Set $2) $2))
+ :__index #(if (. Set $2) $2 nil)
:__newindex (ordered-set-newindex Set)
:__ipairs set-ipairs
:__pairs set-ipairs
@@ -1243,7 +1288,7 @@ using [`conj`](#con) or `tset` functions, and items can be removed
with [`disj`](#disj) or `tset` functions. Rest semantics are the same
as for [`ordered-set`](#ordered-set)
-**Note**: Hash set prints as `#{a b c}`, but this construct is not
+**Note**: Hash set prints as `@set{a b c}`, but this construct is not
supported by the Fennel reader, so you can't create sets with this
syntax. Use `hash-set` function instead."
[& xs]
@@ -1255,12 +1300,12 @@ syntax. Use `hash-set` function instead."
(setmetatable {}
{:cljlib/type :cljlib/hash-set
:cljlib/next #(next Set $2)
+ :cljlib/into into-set
+ :cljlib/empty #(hash-set)
:__eq set-eq
- :__call #(if (. Set $2) $2)
+ :__call #(if (. Set $2) $2 nil)
:__len (set-length Set)
- :__index #(match $2
- :cljlib/empty #(hash-set)
- _ (if (. Set $2) $2))
+ :__index #(if (. Set $2) $2 nil)
:__newindex (hash-set-newindex Set)
:__ipairs set-ipairs
:__pairs set-ipairs
@@ -1281,6 +1326,8 @@ syntax. Use `hash-set` function instead."
multimethods-doc-order
set-doc-order)))
+
;; LocalWords: cljlib Clojure's clj lua PUC mapv concat Clojure fn zs
;; LocalWords: defmulti multi arity eq metadata prepending variadic
-;; LocalWords: args tbl LocalWords memoized referentially
+;; LocalWords: args tbl LocalWords memoized referentially Andrey
+;; LocalWords: Orst codepoints
diff --git a/cljlib-macros.fnl b/macros.fnl
index 19b0107..52a3a94 100644
--- a/cljlib-macros.fnl
+++ b/macros.fnl
@@ -1,13 +1,3 @@
-(local fennel (require :fennel))
-
-
-;;;;;;;;;; compile time check that `--metadata` feature was enabled ;;;;;;;;;;;;
-
-(local meta-enabled (pcall _SCOPE.specials.doc
- (list (sym :doc) (sym :doc))
- _SCOPE _CHUNK))
-
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Helper functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(fn first [tbl]
@@ -53,6 +43,8 @@
(table? (first bindings)))
"expected symbol, sequence or table as binding." bindings)))
+(local fennel (require :fennel))
+
(fn attach-meta [value meta]
(each [k v (pairs meta)]
(fennel.metadata:set value k v)))
@@ -60,9 +52,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;; Runtime function builers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; This code should be shared with `cljlib.fnl` however it seems
-;; impossible to actually do that right now, mainly because there's no
-;; way of doing relative loading of macro modules.
+;; TODO: This code should be shared with `init.fnl`
(fn eq-fn []
;; Returns recursive equality function.
@@ -119,10 +109,16 @@
(insert# assoc-res# [k# v#]))
(if assoc?# assoc-res# res#)))
(= type# :string)
- (let [char# utf8.char]
- (each [_# b# (utf8.codes col#)]
- (insert# res# (char# b#)))
- res#)
+ (if _G.utf8
+ (let [char# _G.utf8.char]
+ (each [_# b# (_G.utf8.codes col#)]
+ (insert# res# (char# b#)))
+ res#)
+ (do
+ (io.stderr:write "WARNING: utf8 module unavailable, seq function will not work for non-unicode strings\n")
+ (each [b# (col#:gmatch ".")]
+ (insert# res# b#))
+ res#))
(= type# :nil) nil
(error "expected table, string or nil" 2)))))
@@ -144,6 +140,11 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Metadata ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; compile time check that `--metadata` feature was enabled
+(local meta-enabled (pcall _SCOPE.specials.doc
+ (list (sym :doc) (sym :doc))
+ _SCOPE _CHUNK))
+
(fn when-meta [...]
"Wrapper that compiles away if metadata support was not enabled. What
this effectively means, is that everything that is wrapped with this
@@ -213,33 +214,57 @@ returns the value without additional metadata.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fn* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(fn keyword? [data]
+ (and (= (type data) :string)
+ (data:find "^[-%w?\\^_!$%&*+./@:|<=>]+$")))
+
+(fn deep-tostring [data key?]
+ (let [tbl []]
+ (if (sequence? data)
+ (do (each [_ v (ipairs data)]
+ (table.insert tbl (deep-tostring v)))
+ (.. "[" (table.concat tbl " ") "]"))
+ (table? data)
+ (do (each [k v (pairs data)]
+ (table.insert tbl (.. (deep-tostring k true) " " (deep-tostring v))))
+ (.. "{" (table.concat tbl " ") "}"))
+ (and key? (keyword? data)) (.. ":" data)
+ (string? data)
+ (string.format "%q" data)
+ (tostring data))))
+
(fn gen-arglist-doc [args]
- ;; Construct vector of arguments represented as strings from AST.
(if (list? (. args 1))
- (let [arglist []
- opener (if (> (length args) 1) "\n (" "(")]
- (each [i v (ipairs args)]
+ (let [arglist []]
+ (each [_ v (ipairs args)]
(let [arglist-doc (gen-arglist-doc v)]
(when (next arglist-doc)
- (table.insert
- arglist
- (.. opener (table.concat arglist-doc " ") ")")))))
+ (table.insert arglist (table.concat arglist-doc " ")))))
+ (when (and (> (length (table.concat arglist " ")) 60)
+ (> (length arglist) 1))
+ (each [i s (ipairs arglist)]
+ (tset arglist i (.. "\n " s))))
arglist)
(sequence? (. args 1))
(let [arglist []
args (. args 1)
len (length args)]
- (each [i v (ipairs args)]
- (table.insert arglist
- (match i
- (1 ? (= len 1)) (.. "[" (tostring v) "]")
- 1 (.. "[" (tostring v))
- len (.. (tostring v) "]")
- _ (tostring v))))
+ (if (= len 0)
+ (table.insert arglist "([])")
+ (each [i v (ipairs args)]
+ (table.insert arglist
+ (match i
+ (1 ? (= len 1)) (.. "([" (deep-tostring v) "])")
+ 1 (.. "([" (deep-tostring v))
+ len (.. (deep-tostring v) "])")
+ _ (deep-tostring v)))))
arglist)))
(fn multisym->sym [s]
+ ;; Strips away the multisym part from symbol, and return just the
+ ;; symbol itself. Also returns the second value of whether the
+ ;; transformation occured or not.
(if (multi-sym? s)
(values (sym (string.gsub (tostring s) ".*[.]" "")) true)
(values s false)))
@@ -293,7 +318,7 @@ returns the value without additional metadata.
(set prev cur))
prev))
-(fn arity-dispatcher [len fixed body& name]
+(fn arity-dispatcher [len fixed amp-body name]
;; Forms an `if` expression with all fixed arities first, then `&` arity,
;; if present, and default error message as last arity.
;;
@@ -304,8 +329,8 @@ returns the value without additional metadata.
;; are put in this `if` as: `(= len fixed-len)`, where `fixed-len` is the
;; length of current arity arglist, computed with `gen-arity`.
;;
- ;; `body&` stores size of fixed part of arglist, that is, everything up
- ;; until `&`, and the body itself. When `body&` provided, the `(>= len
+ ;; `amp-body` stores size of fixed part of arglist, that is, everything up
+ ;; until `&`, and the body itself. When `amp-body` provided, the `(>= len
;; more-len)` is added to the resulting `if` expression.
;;
;; Lastly the catchall branch is added to `if` expression, which ensures
@@ -320,8 +345,8 @@ returns the value without additional metadata.
(table.insert lengths fixed-len)
(table.insert bodies (list '= len fixed-len))
(table.insert bodies body))
- (when body&
- (let [[more-len body arity] body&]
+ (when amp-body
+ (let [[more-len body arity] amp-body]
(assert-compile (not (and max (<= more-len max))) "fn*: arity with `&' must have more arguments than maximum arity without `&'.
* Try adding more arguments before `&'" arity)
@@ -330,7 +355,7 @@ returns the value without additional metadata.
(table.insert bodies body)))
(if (not (and (grows-by-one-or-equal? lengths)
(contains? lengths 0)
- body&))
+ amp-body))
(table.insert bodies (list 'error
(.. "wrong argument amount"
(if name (.. " for " name) "")) 2)))
@@ -352,26 +377,26 @@ returns the value without additional metadata.
;; Produces arglist and all body forms for multi-arity function.
;; For more info check `gen-arity' documentation.
(let [bodies {} ;; bodies of fixed arity
- bodies& []] ;; bodies where arglist contains `&'
+ amp-bodies []] ;; bodies where arglist contains `&'
(each [_ arity (ipairs args)]
(let [(n body amp) (gen-arity arity)]
(if amp
- (table.insert bodies& [amp body arity])
+ (table.insert amp-bodies [amp body arity])
(tset bodies n body))))
- (assert-compile (<= (length bodies&) 1)
+ (assert-compile (<= (length amp-bodies) 1)
"fn* must have only one arity with `&':"
- (. bodies& (length bodies&)))
+ (. amp-bodies (length amp-bodies)))
`(let [len# (select :# ...)]
,(arity-dispatcher
'len#
bodies
- (if (not= (next bodies&) nil)
- (. bodies& 1))
+ (if (not= (next amp-bodies) nil)
+ (. amp-bodies 1))
fname))))
(fn fn* [name doc? ...]
"Create (anonymous) function of fixed arity.
-Supports multiple arities by defining bodies as lists:
+Supports multiple arities by defining bodies as lists.
# Examples
Named function of fixed arity 2:
@@ -511,10 +536,9 @@ from `ns.strings`, so the latter must be fully qualified
(if (sym? name-wo-namespace)
(if namespaced?
`(local ,name-wo-namespace
- (do
- (fn ,name-wo-namespace [...] ,docstring ,body)
- (set ,name ,name-wo-namespace)
- ,(with-meta name-wo-namespace `{:fnl/arglist ,arglist-doc})))
+ (do (fn ,name-wo-namespace [...] ,docstring ,body)
+ (set ,name ,name-wo-namespace) ;; set function into module table, e.g. (set foo.bar bar)
+ ,(with-meta name-wo-namespace `{:fnl/arglist ,arglist-doc})))
`(local ,name ,(with-meta `(fn ,name [...] ,docstring ,body) `{:fnl/arglist ,arglist-doc})))
(with-meta `(fn [...] ,docstring ,body) `{:fnl/arglist ,arglist-doc}))))
@@ -665,9 +689,8 @@ at runtime:
(setmetatable to# {:cljlib/type :seq}))
(= to-type :seq)
`(let [to# (or ,to [])
- seq# ,(seq-fn)
insert# table.insert]
- (each [_# v# (ipairs (seq# (or ,from [])))]
+ (each [_# v# (ipairs (,(seq-fn) (or ,from [])))]
(insert# to# v#))
(setmetatable to# {:cljlib/type :seq}))
(and (= to-type :table) (= from-type :seq))
@@ -683,13 +706,17 @@ at runtime:
(setmetatable to# {:cljlib/type :table}))
(= to-type :table)
`(let [to# (or ,to [])
+ seq# ,(seq-fn)
from# (or ,from [])]
(match (,(table-type-fn) from#)
- :seq (each [_# [k# v#] (ipairs from#)]
+ :seq (each [_# [k# v#] (ipairs (seq# from#))]
(tset to# k# v#))
:table (each [k# v# (pairs from#)]
(tset to# k# v#))
- :else (error "expected table as second argument" 2))
+ :else (error "expected table as second argument" 2)
+ _# (do (each [_# [k# v#] (pairs (or (seq# from#) []))]
+ (tset to# k# v#))
+ to#))
(setmetatable to# {:cljlib/type :table}))
;; runtime branch
`(let [to# ,to
@@ -715,12 +742,10 @@ at runtime:
(tset to# k# v#))
to#)
:empty to#
- :else (error "expected table as second argument" 2))
- ;; set both ordered set and hash set
- (Set# ? (or (= Set# :cljlib/ordered-set) (= Set# :cljlib/hash-set)))
- (do (each [_# v# (ipairs (seq# (or from# [])))]
- (tset to# v# v#))
- to#)
+ :else (error "expected table as second argument" 2)
+ _# (do (each [_# [k# v#] (pairs (or (seq# from#) []))]
+ (tset to# k# v#))
+ to#))
;; sometimes it is handy to pass nil too
:nil (match (table-type# from#)
:nil nil
@@ -732,7 +757,11 @@ at runtime:
(tset to# k# v#))
to#)
:else (error "expected table as second argument" 2))
- :else (error "expected table as first argument" 2))]
+ :else (error "expected table as second argument" 2)
+ _# (let [m# (or (getmetatable to#) {})]
+ (match m#.cljlib/into
+ f# (f# to# from#)
+ nil (error "expected table as SECOND argument" 2))))]
(if res#
(let [m# (or (getmetatable res#) {})]
(set m#.cljlib/type (match to-type#
@@ -769,11 +798,15 @@ See [`into`](#into) for more info on how conversion is done."
(match (table-type x)
:seq `(setmetatable {} {:cljlib/type :seq})
:table `(setmetatable {} {:cljlib/type :table})
- _ `(let [x# ,x]
- (match (,(table-type-fn) x#)
- :cljlib/ordered-set (: x# :cljlib/empty)
- :cljlib/hash-set (: x# :cljlib/empty)
- t# (setmetatable {} {:cljlib/type t#})))))
+ _ `(let [x# ,x
+ m# (getmetatable x#)]
+ (match (and m# m#.cljlib/empty)
+ f# (f# x#)
+ _# (match (,(table-type-fn) x#)
+ :string (setmetatable {} {:cljlib/type :seq})
+ :nil nil
+ :else (error (.. "can't create sequence from " (type x#)))
+ t# (setmetatable {} {:cljlib/type t#}))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; multimethods ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -812,7 +845,7 @@ See [`into`](#into) for more info on how conversion is done."
,docstring
(let [dispatch-value# (,dispatch-fn ...)
(res# view#) (pcall require :fennelview)
- tostr# (if res# view# tostring)]
+ tostr# (if res# #(view# $ {:one-line true}) tostring)]
((or (. t# dispatch-value#)
(. t# (or (. ,options :default) :default))
(error (.. "No method in multimethod '"
@@ -991,9 +1024,11 @@ calls will not override existing bindings:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; try ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(fn catch? [[fun]]
+ "Test if expression is a catch clause."
(= (tostring fun) :catch))
(fn finally? [[fun]]
+ "Test if expression is a finally clause."
(= (tostring fun) :finally))
(fn add-finally [finally form]
diff --git a/tests/core.fnl b/tests/core.fnl
index d323a07..ab62a4b 100644
--- a/tests/core.fnl
+++ b/tests/core.fnl
@@ -1,49 +1,40 @@
-(require-macros :cljlib-macros)
+(require-macros :macros)
(require-macros :tests.test)
-(macro require-module [module]
- "Require module and bind all it's functions to locals."
- `(local ,(let [destr-map# {}]
- (each [k# _# (pairs (require module))]
- (when (not= (string.sub k# 1 1) :_)
- (tset destr-map# k# (sym k#))))
- destr-map#)
- (require ,module)))
-
-(require-module :cljlib)
+(local core (require :init))
(deftest equality
(testing "comparing basetypes"
- (assert-not (pcall eq))
+ (assert-not (pcall core.eq))
(assert-eq 1 1)
(assert-ne 1 2)
- (assert-is (eq 1 1 1 1 1))
+ (assert-is (core.eq 1 1 1 1 1))
(assert-eq 1.0 1.0)
- (assert-is (eq 1.0 1.0 1.0))
- (assert-is (eq 1.0 1.0 1.0))
- (assert-is (eq "1" "1" "1" "1" "1")))
+ (assert-is (core.eq 1.0 1.0 1.0))
+ (assert-is (core.eq 1.0 1.0 1.0))
+ (assert-is (core.eq "1" "1" "1" "1" "1")))
(testing "deep comparison"
- (assert-is (eq []))
+ (assert-is (core.eq []))
(assert-eq [] [])
(assert-eq [] {})
(assert-eq [1 2] [1 2])
(assert-eq [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]
[[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]])
- (assert-is (eq [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]
- [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]))
- (assert-is (eq [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]
- [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]
- [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]))
- (assert-not (eq [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]
- [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]
- [[1 [2 [3]] {[6] {:a [1 [1 [1 [1]]]]}}]]))
+ (assert-is (core.eq [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]
+ [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]))
+ (assert-is (core.eq [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]
+ [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]
+ [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]))
+ (assert-not (core.eq [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]
+ [[1 [2 [3]] {[5] {:a [1 [1 [1 [1]]]]}}]]
+ [[1 [2 [3]] {[6] {:a [1 [1 [1 [1]]]]}}]]))
(assert-ne [1] [1 2])
(assert-ne [1 2] [1])
- (assert-is (eq [1 [2]] [1 [2]] [1 [2]]))
- (assert-is (eq [1 [2]] [1 [2]] [1 [2]]))
- (assert-not (eq [1 [2]] [1 [2]] [1 [2 [3]]]))
- (assert-not (eq {:a {:b 2}} {:a {:b 2}} {:a {:b 3}}))
+ (assert-is (core.eq [1 [2]] [1 [2]] [1 [2]]))
+ (assert-is (core.eq [1 [2]] [1 [2]] [1 [2]]))
+ (assert-not (core.eq [1 [2]] [1 [2]] [1 [2 [3]]]))
+ (assert-not (core.eq {:a {:b 2}} {:a {:b 2}} {:a {:b 3}}))
(let [a {:a 1 :b 2}
b {:a 1 :b 2}]
@@ -74,12 +65,12 @@
meta-b (getmetatable b)
index-a (. meta-a :__index)
index-b (. meta-b :__index)]
- (eq a b)
+ (core.eq a b)
(assert-eq meta-a (getmetatable a))
(assert-eq meta-b (getmetatable b))
(assert-eq index-a (. (getmetatable a) :__index))
(assert-eq index-b (. (getmetatable b) :__index))
- (eq b a)
+ (core.eq b a)
(assert-eq meta-a (getmetatable a))
(assert-eq meta-b (getmetatable b))
(assert-eq index-a (. (getmetatable a) :__index))
@@ -87,189 +78,190 @@
(deftest range
(testing "range"
- (assert-not (pcall range))
- (assert-eq (range 10) [0 1 2 3 4 5 6 7 8 9])
- (assert-eq (range -5 5) [-5 -4 -3 -2 -1 0 1 2 3 4])
+ (assert-not (pcall core.range))
+ (assert-eq (core.range 10) [0 1 2 3 4 5 6 7 8 9])
+ (assert-eq (core.range -5 5) [-5 -4 -3 -2 -1 0 1 2 3 4])
(assert-eq [0 0.2 0.4 0.6 0.8] [0 0.2 0.4 0.6 0.8])
- (assert-eq (range 0 1 0.2) (range 0 1 0.2))))
+ (assert-eq (core.range 0 1 0.2) (core.range 0 1 0.2))))
(deftest predicates
(testing "zero?"
- (assert-is (zero? 0))
- (assert-is (zero? -0))
- (assert-not (zero? 1))
- (assert-not (pcall zero?))
- (assert-not (pcall zero? 1 2)))
+ (assert-is (core.zero? 0))
+ (assert-is (core.zero? -0))
+ (assert-not (core.zero? 1))
+ (assert-not (pcall core.zero?))
+ (assert-not (pcall core.zero? 1 2)))
(testing "int?"
- (assert-is (int? 1))
- (assert-not (int? 1.1))
- (assert-not (pcall int?))
- (assert-not (pcall int? 1 2)))
+ (assert-is (core.int? 1))
+ (assert-not (core.int? 1.1))
+ (assert-not (pcall core.int?))
+ (assert-not (pcall core.int? 1 2)))
(testing "pos?"
- (assert-is (pos? 1))
- (assert-is (and (not (pos? 0)) (not (pos? -1))))
- (assert-not (pcall pos?))
- (assert-not (pcall pos? 1 2)))
+ (assert-is (core.pos? 1))
+ (assert-is (and (not (core.pos? 0)) (not (core.pos? -1))))
+ (assert-not (pcall core.pos?))
+ (assert-not (pcall core.pos? 1 2)))
(testing "neg?"
- (assert-is (neg? -1))
- (assert-is (and (not (neg? 0)) (not (neg? 1))))
- (assert-not (pcall neg?))
- (assert-not (pcall neg? 1 2)))
+ (assert-is (core.neg? -1))
+ (assert-is (and (not (core.neg? 0)) (not (core.neg? 1))))
+ (assert-not (pcall core.neg?))
+ (assert-not (pcall core.neg? 1 2)))
(testing "pos-int?"
- (assert-is (pos-int? 42))
- (assert-not (pos-int? 4.2))
- (assert-not (pcall pos-int?))
- (assert-not (pcall pos-int? 1 2)))
+ (assert-is (core.pos-int? 42))
+ (assert-not (core.pos-int? 4.2))
+ (assert-not (pcall core.pos-int?))
+ (assert-not (pcall core.pos-int? 1 2)))
(testing "neg-int?"
- (assert-is (neg-int? -42))
- (assert-not (neg-int? -4.2))
- (assert-not (pcall neg-int?))
- (assert-not (pcall neg-int? 1 2)))
+ (assert-is (core.neg-int? -42))
+ ;; (assert-not (core.neg-int? -4.2))
+ (assert-not (pcall core.neg-int?))
+ (assert-not (pcall core.neg-int? 1 2)))
(testing "string?"
- (assert-is (string? :s))
- (assert-not (pcall string?))
- (assert-not (pcall string? 1 2)))
+ (assert-is (core.string? :s))
+ (assert-not (pcall core.string?))
+ (assert-not (pcall core.string? 1 2)))
(testing "double?"
- (assert-is (double? 3.3))
- (assert-not (double? 3.0))
- (assert-not (pcall double?))
- (assert-not (pcall double? 1 2)))
+ (assert-is (core.double? 3.3))
+ (assert-not (core.double? 3.0))
+ (assert-not (pcall core.double?))
+ (assert-not (pcall core.double? 1 2)))
(testing "map?"
- (assert-is (map? {:a 1}))
- (assert-not (map? {}))
- (assert-is (map? (empty {})))
- (assert-not (map? (empty [])))
- (assert-not (pcall map?))
- (assert-not (pcall map? 1 2)))
+ (assert-is (core.map? {:a 1}))
+ (assert-not (core.map? {}))
+ (assert-is (core.map? (empty {})))
+ (assert-not (core.map? (empty [])))
+ (assert-not (pcall core.map?))
+ (assert-not (pcall core.map? 1 2)))
(testing "vector?"
- (assert-not (vector? []))
- (assert-is (vector? [{:a 1}]))
- (assert-not (vector? {}))
- (assert-not (vector? {:a 1}))
- (assert-is (vector? (empty [])))
- (assert-not (vector? (empty {})))
- (assert-not (pcall vector?))
- (assert-not (pcall vector? 1 2)))
+ (assert-not (core.vector? []))
+ (assert-is (core.vector? [{:a 1}]))
+ (assert-not (core.vector? {}))
+ (assert-not (core.vector? {:a 1}))
+ (assert-is (core.vector? (empty [])))
+ (assert-not (core.vector? (empty {})))
+ (assert-not (pcall core.vector?))
+ (assert-not (pcall core.vector? 1 2)))
(testing "multifn?"
- (assert-not (multifn? []))
- (assert-is (multifn? (do (defmulti f identity) f)))
- (assert-not (pcall multifn?))
- (assert-not (pcall multifn? 1 2)))
+ (assert-not (core.multifn? []))
+ (assert-is (core.multifn? (do (defmulti f core.identity) f)))
+ (assert-not (pcall core.multifn?))
+ (assert-not (pcall core.multifn? 1 2)))
(testing "set?"
- (assert-is (set? (ordered-set)))
- (assert-is (set? (hash-set)))
- (assert-eq (set? (hash-set)) :cljlib/hash-set)
- (assert-eq (set? (ordered-set)) :cljlib/ordered-set)
- (assert-not (pcall set?))
- (assert-not (pcall set? 1 2)))
+ (assert-is (core.set? (core.ordered-set)))
+ (assert-is (core.set? (core.hash-set)))
+ (assert-eq (core.set? (core.hash-set)) :cljlib/hash-set)
+ (assert-eq (core.set? (core.ordered-set)) :cljlib/ordered-set)
+ (assert-not (pcall core.set?))
+ (assert-not (pcall core.set? 1 2)))
(testing "nil?"
- (assert-is (nil?))
- (assert-is (nil? nil))
- (assert-not (nil? 1))
- (assert-not (pcall nil? 1 2)))
+ (assert-is (core.nil?))
+ (assert-is (core.nil? nil))
+ (assert-not (core.nil? 1))
+ (assert-not (pcall core.nil? 1 2)))
(testing "odd?"
- (assert-is (odd? 3))
- (assert-is (odd? -3))
- (assert-not (odd? 2))
- (assert-not (odd? -2))
- (assert-not (pcall odd?))
- (assert-not (pcall odd? 1 2)))
+ (assert-is (core.odd? 3))
+ (assert-is (core.odd? -3))
+ (assert-not (core.odd? 2))
+ (assert-not (core.odd? -2))
+ (assert-not (pcall core.odd?))
+ (assert-not (pcall core.odd? 1 2)))
(testing "even?"
- (assert-is (even? 2))
- (assert-is (even? -2))
- (assert-not (even? 23))
- (assert-not (even? -23))
- (assert-not (pcall even?))
- (assert-not (pcall even? 1 2)))
+ (assert-is (core.even? 2))
+ (assert-is (core.even? -2))
+ (assert-not (core.even? 23))
+ (assert-not (core.even? -23))
+ (assert-not (pcall core.even?))
+ (assert-not (pcall core.even? 1 2)))
(testing "true?"
- (assert-is (true? true))
- (assert-not (true? false))
- (assert-not (true? 10))
- (assert-not (true? :true))
- (assert-not (pcall true?))
- (assert-not (pcall true? 1 2)))
+ (assert-is (core.true? true))
+ (assert-not (core.true? false))
+ (assert-not (core.true? 10))
+ (assert-not (core.true? :true))
+ (assert-not (pcall core.true?))
+ (assert-not (pcall core.true? 1 2)))
(testing "false?"
- (assert-is (false? false))
- (assert-not (false? true))
- (assert-not (false? 10))
- (assert-not (false? :true))
- (assert-not (pcall false?))
- (assert-not (pcall false? 1 2)))
+ (assert-is (core.false? false))
+ (assert-not (core.false? true))
+ (assert-not (core.false? 10))
+ (assert-not (core.false? :true))
+ (assert-not (pcall core.false?))
+ (assert-not (pcall core.false? 1 2)))
(testing "boolean?"
- (assert-is (boolean? true))
- (assert-is (boolean? false))
- (assert-not (boolean? :false))
- (assert-not (boolean? (fn [] true)))
- (assert-not (pcall boolean?))
- (assert-not (pcall boolean? 1 2))))
+ (assert-is (core.boolean? true))
+ (assert-is (core.boolean? false))
+ (assert-not (core.boolean? :false))
+ (assert-not (core.boolean? (fn [] true)))
+ (assert-not (pcall core.boolean?))
+ (assert-not (pcall core.boolean? 1 2))))
(deftest sequence-functions
(testing "seq"
- (assert-not (pcall seq))
- (assert-not (pcall seq [] []))
- (assert-eq (seq []) nil)
- (assert-eq (seq {}) nil)
- (assert-eq (seq [1]) [1])
- (assert-eq (seq [1 2 3]) [1 2 3])
- (assert-eq (seq {:a 1}) [["a" 1]])
- (assert-eq (seq "abc") ["a" "b" "c"])
- (assert-eq (seq "абв") ["а" "б" "в"])
- (assert-eq (seq {12345 123}) [[12345 123]])
- (assert-eq (seq (ordered-set 1 2 3)) [1 2 3])
- (assert-eq (length (seq (ordered-set 1 2 3))) 3)
- (assert-eq (seq (hash-set 1)) [1])
- (assert-eq (length (seq (hash-set 1 2 3))) 3))
+ (assert-not (pcall core.seq))
+ (assert-not (pcall core.seq [] []))
+ (assert-eq (core.seq []) nil)
+ (assert-eq (core.seq {}) nil)
+ (assert-eq (core.seq [1]) [1])
+ (assert-eq (core.seq [1 2 3]) [1 2 3])
+ (assert-eq (core.seq {:a 1}) [["a" 1]])
+ (assert-eq (core.seq "abc") ["a" "b" "c"])
+ (when _G.utf8 (assert-eq (core.seq "абв") ["а" "б" "в"]))
+ (assert-eq (core.seq {12345 123}) [[12345 123]])
+ (assert-eq (core.seq (core.ordered-set 1 2 3)) [1 2 3])
+ (assert-eq (length (core.seq (core.ordered-set 1 2 3))) 3)
+ (assert-eq (core.seq (core.hash-set 1)) [1])
+ (assert-eq (length (core.seq (core.hash-set 1 2 3))) 3))
(testing "kvseq"
- (assert-not (pcall kvseq))
- (assert-not (pcall kvseq [] []))
- (assert-eq (kvseq {123 456}) [[123 456]])
- (assert-eq (kvseq {:a 1}) [[:a 1]])
- (assert-eq (kvseq [0 0 0 10]) [[1 0] [2 0] [3 0] [4 10]])
- (assert-eq (kvseq (ordered-set :a :b :c)) [[1 :a] [2 :b] [3 :c]])
- (assert-eq (kvseq (hash-set :a)) [[1 :a]]))
+ (assert-not (pcall core.kvseq))
+ (assert-not (pcall core.kvseq [] []))
+ (assert-eq (core.kvseq {123 456}) [[123 456]])
+ (assert-eq (core.kvseq {:a 1}) [[:a 1]])
+ (assert-eq (core.kvseq [0 0 0 10]) [[1 0] [2 0] [3 0] [4 10]])
+ (assert-eq (core.kvseq (core.ordered-set :a :b :c)) [[1 :a] [2 :b] [3 :c]])
+ (assert-eq (core.kvseq (core.hash-set :a)) [[1 :a]])
+ (assert-eq (core.kvseq "abc") [[1 "a"] [2 "b"] [3 "c"]]))
(testing "mapv"
- (assert-not (pcall mapv))
- (assert-not (pcall mapv #(do nil)))
- (assert-eq (mapv #(* $ $) [1 2 3 4]) [1 4 9 16])
+ (assert-not (pcall core.mapv))
+ (assert-not (pcall core.mapv #(do nil)))
+ (assert-eq (core.mapv #(* $ $) [1 2 3 4]) [1 4 9 16])
- (assert-eq (into {} (mapv (fn [[k v]] [k (* v v)]) {:a 1 :b 2 :c 3}))
+ (assert-eq (into {} (core.mapv (fn [[k v]] [k (* v v)]) {:a 1 :b 2 :c 3}))
(into {} [[:a 1] [:b 4] [:c 9]]))
- (assert-eq (into {} (mapv (fn [[k1 v1] [k2 v2]] [k1 (* v1 v2)])
- {:a 1 :b 2 :c 3}
- {:a -1 :b 0 :c 2}))
+ (assert-eq (into {} (core.mapv (fn [[k1 v1] [k2 v2]] [k1 (* v1 v2)])
+ {:a 1 :b 2 :c 3}
+ {:a -1 :b 0 :c 2}))
{:a -1 :b 0 :c 6})
- (assert-eq (mapv #(* $1 $2 $3) [1] [2] [-1]) [-2])
- (assert-eq (mapv string.upper ["a" "b" "c"]) ["A" "B" "C"])
- (assert-eq (mapv #(+ $1 $2 $3 $4) [1 -1] [2 -2] [3 -3] [4 -4]) [(+ 1 2 3 4) (+ -1 -2 -3 -4)])
- (assert-eq (mapv (fn [f-name s-name company position]
- (.. f-name " " s-name " works as " position " at " company))
- ["Bob" "Alice"]
- ["Smith" "Watson"]
- ["Happy Days co." "Coffee With You"]
- ["secretary" "chief officer"])
+ (assert-eq (core.mapv #(* $1 $2 $3) [1] [2] [-1]) [-2])
+ (assert-eq (core.mapv string.upper ["a" "b" "c"]) ["A" "B" "C"])
+ (assert-eq (core.mapv #(+ $1 $2 $3 $4) [1 -1] [2 -2] [3 -3] [4 -4]) [(+ 1 2 3 4) (+ -1 -2 -3 -4)])
+ (assert-eq (core.mapv (fn [f-name s-name company position]
+ (.. f-name " " s-name " works as " position " at " company))
+ ["Bob" "Alice"]
+ ["Smith" "Watson"]
+ ["Happy Days co." "Coffee With You"]
+ ["secretary" "chief officer"])
["Bob Smith works as secretary at Happy Days co."
"Alice Watson works as chief officer at Coffee With You"])
- (assert-eq (table.concat (mapv string.upper "vaiv")) "VAIV"))
+ (assert-eq (table.concat (core.mapv string.upper "vaiv")) "VAIV"))
(testing "reduce"
(fn* add
@@ -282,18 +274,18 @@
(set res (+ res v)))
res))
- (assert-eq (reduce add []) 0)
- (assert-eq (reduce add [1]) 1)
- (assert-eq (reduce add [1 2]) 3)
- (assert-eq (reduce add (range 10)) 45)
- (assert-eq (reduce add -3 (range 10)) 42)
- (assert-eq (reduce add 10 []) 10)
- (assert-eq (reduce add 10 [1]) 11)
- (assert-eq (reduce add 10 nil) 10)
- (assert-not (pcall reduce))
- (assert-not (pcall reduce add)))
-
- (testing "reduce reference implementation"
+ (assert-eq (core.reduce add []) 0)
+ (assert-eq (core.reduce add [1]) 1)
+ (assert-eq (core.reduce add [1 2]) 3)
+ (assert-eq (core.reduce add (core.range 10)) 45)
+ (assert-eq (core.reduce add -3 (core.range 10)) 42)
+ (assert-eq (core.reduce add 10 []) 10)
+ (assert-eq (core.reduce add 10 [1]) 11)
+ (assert-eq (core.reduce add 10 nil) 10)
+ (assert-not (pcall core.reduce))
+ (assert-not (pcall core.reduce add)))
+
+ (testing "core.reduce reference implementation"
(fn mapping [f]
(fn [reducing]
(fn [result input]
@@ -302,168 +294,173 @@
(fn -reduce [f init [x & tbl]]
(if x (-reduce f (f init x) tbl) init))
- (assert-eq (reduce add (range 10)) (-reduce add 0 (range 10)))
- (assert-eq (reduce ((mapping inc) add) 0 (range 10))
- (-reduce ((mapping inc) add) 0 (range 10))))
+ (assert-eq (core.reduce core.add (core.range 10)) (-reduce core.add 0 (core.range 10)))
+ (assert-eq (core.reduce ((mapping core.inc) core.add) 0 (core.range 10))
+ (-reduce ((mapping core.inc) core.add) 0 (core.range 10))))
(testing "filter"
- (assert-not (pcall filter))
- (assert-not (pcall filter even?))
- (assert-eq (filter even? (range 10)) [0 2 4 6 8])
- (assert-eq (filter odd? (range 10)) [1 3 5 7 9])
- (assert-eq (filter map? [{:a 1} {5 1} [1 2] [] {}]) [{:a 1} {5 1}])
- (assert-eq (filter vector? [{:a 1} {5 1} [1 2] [] {}]) [[1 2]]))
+ (assert-not (pcall core.filter))
+ (assert-not (pcall core.filter core.even?))
+ (assert-eq (core.filter core.even? (core.range 10)) [0 2 4 6 8])
+ (assert-eq (core.filter core.odd? (core.range 10)) [1 3 5 7 9])
+ (assert-eq (core.filter core.map? [{:a 1} {5 1} [1 2] [] {}]) [{:a 1} {5 1}])
+ (assert-eq (core.filter core.vector? [{:a 1} {5 1} [1 2] [] {}]) [[1 2]]))
(testing "concat"
- (assert-eq (concat) nil)
- (assert-eq (concat []) [])
- (assert-eq (concat [1 2 3]) [1 2 3])
- (assert-eq (concat [1 2 3] [4 5 6]) [1 2 3 4 5 6])
- (assert-eq (concat [1 2] [3 4] [5 6]) [1 2 3 4 5 6])
- (assert-eq (concat {:a 1} {:b 2}) [[:a 1] [:b 2]])
- (assert-eq (concat [[:a 1]] {:b 2}) [[:a 1] [:b 2]])
- (assert-eq (concat {:a 1} [[:b 2]]) [[:a 1] [:b 2]])
- (assert-eq (concat [] [[:b 2]]) [[:b 2]])
- (assert-eq (concat [] []) [])
- (assert-not (pcall concat 1))
- (assert-not (pcall concat 1 2))
- (assert-not (pcall concat 1 []))
- (assert-not (pcall concat [] 2))
- (assert-not (pcall concat [1] 2)))
+ (assert-eq (core.concat) nil)
+ (assert-eq (core.concat []) [])
+ (assert-eq (core.concat [1 2 3]) [1 2 3])
+ (assert-eq (core.concat [1 2 3] [4 5 6]) [1 2 3 4 5 6])
+ (assert-eq (core.concat [1 2] [3 4] [5 6]) [1 2 3 4 5 6])
+ (assert-eq (core.concat {:a 1} {:b 2}) [[:a 1] [:b 2]])
+ (assert-eq (core.concat [[:a 1]] {:b 2}) [[:a 1] [:b 2]])
+ (assert-eq (core.concat {:a 1} [[:b 2]]) [[:a 1] [:b 2]])
+ (assert-eq (core.concat [] [[:b 2]]) [[:b 2]])
+ (assert-eq (core.concat [] []) [])
+ (assert-not (pcall core.concat 1))
+ (assert-not (pcall core.concat 1 2))
+ (assert-not (pcall core.concat 1 []))
+ (assert-not (pcall core.concat [] 2))
+ (assert-not (pcall core.concat [1] 2)))
(testing "reverse"
- (assert-not (pcall reverse))
- (assert-not (pcall reverse [] []))
- (assert-eq (reverse []) nil)
- (assert-eq (reverse [1 2 3]) [3 2 1])
- (assert-eq (reverse {:a 1}) [[:a 1]]))
+ (assert-not (pcall core.reverse))
+ (assert-not (pcall core.reverse [] []))
+ (assert-eq (core.reverse []) nil)
+ (assert-eq (core.reverse [1 2 3]) [3 2 1])
+ (assert-eq (core.reverse {:a 1}) [[:a 1]]))
(testing "conj"
- (assert-eq (conj) [])
- (assert-eq (conj [1]) [1])
- (assert-eq (conj [] 1 2 3) [1 2 3])
- (assert-eq (conj [0] 1 2 3) [0 1 2 3])
- (assert-eq (conj {:a 1} [:b 2]) {:a 1 :b 2})
- (assert-eq (conj {:a 1}) {:a 1})
- (assert-eq (conj [1] 2 3 4 5 6 7) [1 2 3 4 5 6 7]))
+ (assert-eq (core.conj) [])
+ (assert-eq (core.conj [1]) [1])
+ (assert-eq (core.conj [] 1 2 3) [1 2 3])
+ (assert-eq (core.conj [0] 1 2 3) [0 1 2 3])
+ (assert-eq (core.conj {:a 1} [:b 2]) {:a 1 :b 2})
+ (assert-eq (core.conj {:a 1}) {:a 1})
+ (assert-eq (core.conj [1] 2 3 4 5 6 7) [1 2 3 4 5 6 7]))
(testing "disj"
- (assert-not (pcall disj))
- (assert-not (pcall disj [1]))
- (assert-not (pcall disj [1] 1))
- (assert-eq (disj (ordered-set)) (ordered-set))
- (assert-eq (disj (ordered-set 1 3 2 5) 3) (ordered-set 1 2 5))
- (assert-eq (disj (ordered-set 1 3 2 5) 3 1 5) (ordered-set 2)))
+ (assert-not (pcall core.disj))
+ (assert-not (pcall core.disj [1]))
+ (assert-not (pcall core.disj [1] 1))
+ (assert-eq (core.disj (core.ordered-set)) (core.ordered-set))
+ (assert-eq (core.disj (core.ordered-set 1 3 2 5) 3) (core.ordered-set 1 2 5))
+ (assert-eq (core.disj (core.ordered-set 1 3 2 5) 3 1 5) (core.ordered-set 2)))
(testing "cons"
- (assert-not (pcall cons))
- (assert-not (pcall cons [] [] []))
- (assert-eq (cons nil [1]) [1])
- (assert-eq (cons 1 []) [1])
- (assert-eq (cons 1 [0]) [1 0]))
+ (assert-not (pcall core.cons))
+ (assert-not (pcall core.cons [] [] []))
+ (assert-eq (core.cons nil [1]) [1])
+ (assert-eq (core.cons 1 []) [1])
+ (assert-eq (core.cons 1 [0]) [1 0]))
(testing "first"
- (assert-not (pcall first))
- (assert-not (pcall first [] []))
- (assert-eq (first [1 2 3]) 1)
- (assert-eq (first {:a 1}) [:a 1])
- (assert-eq (first []) nil))
+ (assert-not (pcall core.first))
+ (assert-not (pcall core.first [] []))
+ (assert-eq (core.first [1 2 3]) 1)
+ (assert-eq (core.first {:a 1}) [:a 1])
+ (assert-eq (core.first []) nil))
(testing "last"
- (assert-not (pcall last))
- (assert-not (pcall last [] []))
- (assert-eq (last [1 2 3]) 3)
- (assert-eq (last []) nil)
- (assert-eq (last nil) nil)
- (assert-eq (last {:a 1}) [:a 1]))
+ (assert-not (pcall core.last))
+ (assert-not (pcall core.last [] []))
+ (assert-eq (core.last [1 2 3]) 3)
+ (assert-eq (core.last []) nil)
+ (assert-eq (core.last nil) nil)
+ (assert-eq (core.last {:a 1}) [:a 1]))
(testing "rest"
- (assert-not (pcall rest))
- (assert-not (pcall rest [] []))
- (assert-eq (rest [1 2 3]) [2 3])
- (assert-eq (rest {:a 1}) [])
- (assert-eq (rest []) [])
- (assert-eq (rest nil) []))
+ (assert-not (pcall core.rest))
+ (assert-not (pcall core.rest [] []))
+ (assert-eq (core.rest [1 2 3]) [2 3])
+ (assert-eq (core.rest {:a 1}) [])
+ (assert-eq (core.rest []) [])
+ (assert-eq (core.rest nil) []))
(testing "butlast"
- (assert-not (pcall butlast))
- (assert-not (pcall butlast [] []))
- (assert-eq (butlast [1 2 3]) [1 2])
- (assert-eq (butlast {:a 1}) nil)
- (assert-eq (butlast []) nil)
- (assert-eq (butlast nil) nil))
+ (assert-not (pcall core.butlast))
+ (assert-not (pcall core.butlast [] []))
+ (assert-eq (core.butlast [1 2 3]) [1 2])
+ (assert-eq (core.butlast {:a 1}) nil)
+ (assert-eq (core.butlast []) nil)
+ (assert-eq (core.butlast nil) nil))
(testing "reduce-kv"
- (assert-eq (reduce-kv #(+ $1 $3) 0 {:a 1 :b 2 :c 3}) 6)
- (assert-eq (reduce-kv #(+ $1 $3) 0 [1 2 3]) 6)
- (assert-not (pcall reduce-kv #(+ $1 $3) 0))
- (assert-not (pcall reduce-kv #(+ $1 $3)))
- (assert-not (pcall reduce-kv)))
+ (assert-eq (core.reduce-kv #(+ $1 $3) 0 {:a 1 :b 2 :c 3}) 6)
+ (assert-eq (core.reduce-kv #(+ $1 $3) 0 [1 2 3]) 6)
+ (assert-not (pcall core.reduce-kv #(+ $1 $3) 0))
+ (assert-not (pcall core.reduce-kv #(+ $1 $3)))
+ (assert-not (pcall core.reduce-kv)))
(testing "reduced"
- (assert-not (pcall reduced))
- (assert-not (pcall reduced 1 2 3))
- (assert-eq (reduce #(if (> $1 10) (reduced -1) (+ $1 $2)) [1]) 1)
- (assert-eq (reduce #(if (> $1 10) (reduced -1) (+ $1 $2)) [1 2]) 3)
- (assert-eq (reduce #(if (> $1 10) (reduced -1) (+ $1 $2)) [1 2 3 4]) 10)
- (assert-eq (reduce #(if (> $1 10) (reduced -1) (+ $1 $2)) [1 2 3 4 5]) 15)
- (assert-eq (reduce #(if (> $1 10) (reduced -1) (+ $1 $2)) [1 2 3 4 5 6]) -1)
- (assert-eq (reduce #(if (> $1 10) (reduced -1) (+ $1 $2)) 10 [1]) 11)
- (assert-eq (reduce #(if (> $1 10) (reduced -1) (+ $1 $2)) 10 [1 2]) -1)
- (assert-eq (reduce #(if (> $1 10) (reduced -1) (+ $1 $2)) 0 [10 5]) 15)
- (assert-eq (reduce #(if (> $1 10) (reduced -1) (+ $1 $2)) 1 [10 7]) -1)
-
- (assert-eq (reduce-kv (fn [res _ v] (if (> res 10) (reduced -1) (+ res v))) 0 {:a 1 :b 2}) 3)
- (assert-eq (reduce-kv (fn [res _ v] (if (> res 10) (reduced -1) (+ res v))) 0 {:a 10 :b 2}) 12)
- (assert-eq (reduce-kv (fn [res _ v] (if (> res 10) (reduced -1) (+ res v))) 1 {:a 3 :b 3 :c 3 :d 3}) 13)
- (assert-eq (reduce-kv (fn [res _ v] (if (> res 10) (reduced -1) (+ res v))) 2 {:a 3 :b 3 :c 3 :d 3}) -1)
- (assert-eq (reduce-kv (fn [res _ v] (if (> res 10) (reduced -1) (+ res v))) 1 [10 12]) -1))
+ (assert-not (pcall core.reduced))
+ (assert-not (pcall core.reduced 1 2 3))
+ (assert-eq (core.reduce #(if (> $1 10) (core.reduced -1) (+ $1 $2)) [1]) 1)
+ (assert-eq (core.reduce #(if (> $1 10) (core.reduced -1) (+ $1 $2)) [1 2]) 3)
+ (assert-eq (core.reduce #(if (> $1 10) (core.reduced -1) (+ $1 $2)) [1 2 3 4]) 10)
+ (assert-eq (core.reduce #(if (> $1 10) (core.reduced -1) (+ $1 $2)) [1 2 3 4 5]) 15)
+ (assert-eq (core.reduce #(if (> $1 10) (core.reduced -1) (+ $1 $2)) [1 2 3 4 5 6]) -1)
+ (assert-eq (core.reduce #(if (> $1 10) (core.reduced -1) (+ $1 $2)) 10 [1]) 11)
+ (assert-eq (core.reduce #(if (> $1 10) (core.reduced -1) (+ $1 $2)) 10 [1 2]) -1)
+ (assert-eq (core.reduce #(if (> $1 10) (core.reduced -1) (+ $1 $2)) 0 [10 5]) 15)
+ (assert-eq (core.reduce #(if (> $1 10) (core.reduced -1) (+ $1 $2)) 1 [10 7]) -1)
+
+ (assert-eq (core.reduce-kv (fn [res _ v] (if (> res 10) (core.reduced -1) (+ res v))) 0 {:a 1 :b 2}) 3)
+ (assert-eq (core.reduce-kv (fn [res _ v] (if (> res 10) (core.reduced -1) (+ res v))) 0 {:a 10 :b 2}) 12)
+ (assert-eq (core.reduce-kv (fn [res _ v] (if (> res 10) (core.reduced -1) (+ res v))) 1 {:a 3 :b 3 :c 3 :d 3}) 13)
+ (assert-eq (core.reduce-kv (fn [res _ v] (if (> res 10) (core.reduced -1) (+ res v))) 2 {:a 3 :b 3 :c 3 :d 3}) -1)
+ (assert-eq (core.reduce-kv (fn [res _ v] (if (> res 10) (core.reduced -1) (+ res v))) 1 [10 12]) -1))
(testing "assoc"
- (assert-not (pcall assoc))
- (assert-not (pcall assoc {}))
- (assert-eq (assoc {} :a 1) {:a 1})
- (assert-eq (assoc {} :a 1 :b 2 :c 3 :d 4) {:a 1 :b 2 :c 3 :d 4}))
+ (assert-not (pcall core.assoc))
+ (assert-not (pcall core.assoc {}))
+ (assert-eq (core.assoc {} :a 1) {:a 1})
+ (assert-eq (core.assoc {} :a 1 :b 2 :c 3 :d 4) {:a 1 :b 2 :c 3 :d 4}))
(testing "dissoc"
- (assert-not (pcall dissoc))
- (assert-eq (dissoc {}) {})
- (assert-eq (dissoc {:a 1 :b 2} :b) {:a 1})
- (assert-eq (dissoc {:a 1 :b 2 :c 3} :a :c) {:b 2}))
+ (assert-not (pcall core.dissoc))
+ (assert-eq (core.dissoc {}) {})
+ (assert-eq (core.dissoc {:a 1 :b 2} :b) {:a 1})
+ (assert-eq (core.dissoc {:a 1 :b 2 :c 3} :a :c) {:b 2}))
(testing "find, keys and vals"
- (assert-not (pcall keys))
- (assert-not (pcall keys {} {} {}))
- (assert-not (pcall vals))
- (assert-not (pcall vals {} {} {}))
- (assert-not (pcall find))
- (assert-not (pcall find {} {} {}))
- (assert-eq (keys {:a 1 :b 2 :c 3}) (hash-set :a :b :c))
- (assert-eq (vals {:a 1 :b 2 :c 3}) (hash-set 1 2 3))
- (assert-eq (find {:a 1 :b 2 :c 3} :c) [:c 3])
- (assert-eq (find {:a 1 :b 2 :c 3} :d) nil)))
+ (assert-not (pcall core.keys))
+ (assert-not (pcall core.keys {} {} {}))
+ (assert-not (pcall core.vals))
+ (assert-not (pcall core.vals {} {} {}))
+ (assert-not (pcall core.find))
+ (assert-not (pcall core.find {} {} {}))
+ (assert-eq (core.keys {:a 1}) [:a])
+ (assert-eq (core.vals {:a 1}) [1])
+ (match (pcall #(assert-eq (core.keys {:a 1 :b 2 :c 3}) (core.hash-set :a :b :c)))
+ (false msg) (io.stderr:write (.. "WARNING: " msg)))
+ (match (pcall #(assert-eq (core.vals {:a 1 :b 2 :c 3}) (core.hash-set 1 2 3)))
+ (false msg) (io.stderr:write (.. "WARNING: " msg)))
+ (assert-eq (core.find {:a 1 :b 2 :c 3} :c) [:c 3])
+ (assert-eq (core.find {:a 1 :b 2 :c 3} :d) nil)))
+
(deftest function-manipulation
(testing "constantly"
- (assert-not (pcall constantly))
- (assert-not (pcall constantly nil nil))
- (let [always-nil (constantly nil)]
+ (assert-not (pcall core.constantly))
+ (assert-not (pcall core.constantly nil nil))
+ (let [always-nil (core.constantly nil)]
(assert-eq (always-nil) nil)
(assert-eq (always-nil 1) nil)
(assert-eq (always-nil 1 2 3 4 "5") nil))
- (let [always-true (constantly true)]
+ (let [always-true (core.constantly true)]
(assert-is (always-true))
(assert-is (always-true false))))
(testing "complement"
- (assert-not (pcall complement))
- (assert-not (pcall complement #nil #nil))
- (assert-is ((complement #(do false))))
- (assert-is ((complement nil?) 10))
- (assert-is ((complement every?) double? [1 2 3 4]))
- (assert-is ((complement #(= $1 $2 $3)) 1 1 2 1))
- (assert-is ((complement #(= $1 $2)) 1 2)))
+ (assert-not (pcall core.complement))
+ (assert-not (pcall core.complement #nil #nil))
+ (assert-is ((core.complement #(do false))))
+ (assert-is ((core.complement core.nil?) 10))
+ (assert-is ((core.complement core.every?) core.double? [1 2 3 4]))
+ (assert-is ((core.complement #(= $1 $2 $3)) 1 1 2 1))
+ (assert-is ((core.complement #(= $1 $2)) 1 2)))
(testing "apply"
(fn* add
@@ -471,325 +468,329 @@
([x y] (+ x y))
([x y & zs]
(add (+ x y) ((or _G.unpack table.unpack) zs))))
- (assert-eq (apply add [1 2 3 4]) 10)
- (assert-eq (apply add -1 [1 2 3 4]) 9)
- (assert-eq (apply add -2 -1 [1 2 3 4]) 7)
- (assert-eq (apply add -3 -2 -1 [1 2 3 4]) 4)
- (assert-eq (apply add -4 -3 -2 -1 [1 2 3 4]) 0)
- (assert-eq (apply add -5 -4 -3 -2 -1 [1 2 3 4]) -5)
- (assert-not (pcall apply))
- (assert-not (pcall apply add)))
+ (assert-eq (core.apply add [1 2 3 4]) 10)
+ (assert-eq (core.apply add -1 [1 2 3 4]) 9)
+ (assert-eq (core.apply add -2 -1 [1 2 3 4]) 7)
+ (assert-eq (core.apply add -3 -2 -1 [1 2 3 4]) 4)
+ (assert-eq (core.apply add -4 -3 -2 -1 [1 2 3 4]) 0)
+ (assert-eq (core.apply add -5 -4 -3 -2 -1 [1 2 3 4]) -5)
+ (assert-not (pcall core.apply))
+ (assert-not (pcall core.apply add)))
(testing "comp"
- (assert-eq ((comp) 10) 10)
- (assert-eq ((comp #10)) 10)
+ (assert-eq ((core.comp) 10) 10)
+ (assert-eq ((core.comp #10)) 10)
(fn square [x] (* x x))
- (assert-eq (comp square) square)
- (assert-eq ((comp square inc) 6) 49)
- (assert-eq ((comp #(- $ 7) square inc inc inc inc inc inc inc) 0) 42)
+ (assert-eq (core.comp square) square)
+ (assert-eq ((core.comp square core.inc) 6) 49)
+ (assert-eq ((core.comp #(- $ 7) square core.inc core.inc core.inc core.inc core.inc core.inc core.inc) 0) 42)
(fn sum-squares [x y] (+ (* x x) (* y y)))
- (assert-eq ((comp square inc sum-squares) 2 3) 196)
+ (assert-eq ((core.comp square core.inc sum-squares) 2 3) 196)
(fn f [a b c] (+ a b c))
- (assert-eq ((comp inc f) 1 2 3) 7)
+ (assert-eq ((core.comp core.inc f) 1 2 3) 7)
(fn g [a b c d] (+ a b c d))
- (assert-eq ((comp inc g) 1 2 3 4) 11)
+ (assert-eq ((core.comp core.inc g) 1 2 3 4) 11)
(fn h [a b c d e f] (+ a b c d e f))
- (assert-eq ((comp inc h) 1 2 3 4 5 6) 22))
+ (assert-eq ((core.comp core.inc h) 1 2 3 4 5 6) 22))
(testing "identity"
(fn f [] nil)
(local a {})
- (assert-not (pcall identity))
- (assert-not (pcall identity 1 2))
- (assert-eq (identity 1) 1)
- (assert-eq (identity {:a 1 :b 2}) {:a 1 :b 2})
- (assert-eq (identity [1 2 3]) [1 2 3])
- (assert-eq (identity "abc") "abc")
- (assert-eq (identity f) f)
- (assert-eq (identity a) a)))
+ (assert-not (pcall core.identity))
+ (assert-not (pcall core.identity 1 2))
+ (assert-eq (core.identity 1) 1)
+ (assert-eq (core.identity {:a 1 :b 2}) {:a 1 :b 2})
+ (assert-eq (core.identity [1 2 3]) [1 2 3])
+ (assert-eq (core.identity "abc") "abc")
+ (assert-eq (core.identity f) f)
+ (assert-eq (core.identity a) a)))
(deftest sequence-predicates
(testing "some"
- (assert-not (pcall some))
- (assert-not (pcall some pos-int?))
- (assert-is (some pos-int? [-1 1.1 2.3 -5.5 42 10 -27]))
- (assert-not (some pos-int? {:a 1}))
- (assert-is (some pos-int? [{:a 1} "1" -1 1])))
+ (assert-not (pcall core.some))
+ (assert-not (pcall core.some core.pos-int?))
+ (assert-is (core.some core.pos-int? [-1 1.1 2.3 -55 42 10 -27]))
+ (assert-not (core.some core.pos-int? {:a 1}))
+ (assert-is (core.some core.pos-int? [{:a 1} "1" -1 1])))
(testing "not-any?"
- (assert-not (pcall not-any?))
- (assert-not (pcall not-any? pos-int?))
- (assert-is (not-any? pos-int? [-1 1.1 2.3 -5.5 -42 -10 -27]))
- (assert-is (not-any? pos-int? {:a 1}))
- (assert-not (not-any? pos-int? [1 2 3 4 5])))
+ (assert-not (pcall core.not-any?))
+ (assert-not (pcall core.not-any? core.pos-int?))
+ (assert-is (core.not-any? core.pos-int? [-1 1.1 2.3 -55 -42 -10 -27]))
+ (assert-is (core.not-any? core.pos-int? {:a 1}))
+ (assert-not (core.not-any? core.pos-int? [1 2 3 4 5])))
(testing "every?"
- (assert-not (pcall every?))
- (assert-not (pcall every? pos-int?))
- (assert-not (every? pos-int? [-1 1.1 2.3 -5.5 42 10 -27]))
- (assert-not (every? pos-int? {:a 1}))
- (assert-is (every? pos-int? [1 2 3 4 5])))
+ (assert-not (pcall core.every?))
+ (assert-not (pcall core.every? core.pos-int?))
+ (assert-not (core.every? core.pos-int? [-1 1.1 2.3 -55 42 10 -27]))
+ (assert-not (core.every? core.pos-int? {:a 1}))
+ (assert-is (core.every? core.pos-int? [1 2 3 4 5])))
(testing "empty?"
- (assert-not (pcall empty?))
- (assert-is (empty? []))
- (assert-is (empty? {}))
- (assert-is (empty? ""))
- (assert-not (empty? "1"))
- (assert-not (empty? [1]))
- (assert-not (empty? {:a 1}))
- (assert-not (pcall empty? 10)))
+ (assert-not (pcall core.empty?))
+ (assert-is (core.empty? []))
+ (assert-is (core.empty? {}))
+ (assert-is (core.empty? ""))
+ (assert-not (core.empty? "1"))
+ (assert-not (core.empty? [1]))
+ (assert-not (core.empty? {:a 1}))
+ (assert-not (pcall core.empty? 10)))
(testing "not-empty"
- (assert-not (pcall not-empty))
- (assert-eq (not-empty []) nil)
- (assert-eq (not-empty {}) nil)
- (assert-eq (not-empty "") nil)
- (assert-eq (not-empty "1") "1")
- (assert-eq (not-empty [1]) [1])
- (assert-eq (not-empty {:a 1}) {:a 1})))
+ (assert-not (pcall core.not-empty))
+ (assert-eq (core.not-empty []) nil)
+ (assert-eq (core.not-empty {}) nil)
+ (assert-eq (core.not-empty "") nil)
+ (assert-eq (core.not-empty "1") "1")
+ (assert-eq (core.not-empty [1]) [1])
+ (assert-eq (core.not-empty {:a 1}) {:a 1})))
(deftest math-functions
(testing "inc"
- (assert-eq (inc 1) 2)
- (assert-eq (inc -1) 0)
- (assert-not (pcall inc))
- (assert-not (pcall inc nil)))
+ (assert-eq (core.inc 1) 2)
+ (assert-eq (core.inc -1) 0)
+ (assert-not (pcall core.inc))
+ (assert-not (pcall core.inc nil)))
(testing "dec"
- (assert-eq (dec 1) 0)
- (assert-eq (dec -1) -2)
- (assert-not (pcall dec))
- (assert-not (pcall dec nil))))
+ (assert-eq (core.dec 1) 0)
+ (assert-eq (core.dec -1) -2)
+ (assert-not (pcall core.dec))
+ (assert-not (pcall core.dec nil))))
(deftest table-access
(testing "get"
- (assert-eq (get {:key1 10 :key2 20} :key1) 10)
- (assert-eq (get {:key1 10 :key2 20} :key1 false) 10)
- (assert-eq (get {:key1 10 :key2 20} :key3 false) false)
- (assert-eq (get {:key1 10 :key2 20} :key3) nil)
- (assert-not (pcall get))
- (assert-not (pcall get {})))
+ (assert-eq (core.get {:key1 10 :key2 20} :key1) 10)
+ (assert-eq (core.get {:key1 10 :key2 20} :key1 false) 10)
+ (assert-eq (core.get {:key1 10 :key2 20} :key3 false) false)
+ (assert-eq (core.get {:key1 10 :key2 20} :key3) nil)
+ (assert-not (pcall core.get))
+ (assert-not (pcall core.get {})))
(testing "get-in"
(local t {:a {:b {:c 10}}})
- (assert-eq (get-in t [:a]) {:b {:c 10}})
- (assert-eq (get-in t [:a :b]) {:c 10})
- (assert-eq (get-in t [:a :b :c]) 10)
- (assert-eq (get-in t [:a :b :c] false) 10)
- (assert-eq (get-in t [:a :b :d] false) false)
- (assert-eq (get-in t [:a :b :d]) nil)
- (assert-eq (get-in t []) t)
- (assert-not (pcall get-in))
- (assert-not (pcall get-in {}))))
+ (assert-eq (core.get-in t [:a]) {:b {:c 10}})
+ (assert-eq (core.get-in t [:a :b]) {:c 10})
+ (assert-eq (core.get-in t [:a :b :c]) 10)
+ (assert-eq (core.get-in t [:a :b :c] false) 10)
+ (assert-eq (core.get-in t [:a :b :d] false) false)
+ (assert-eq (core.get-in t [:a :b :d]) nil)
+ (assert-eq (core.get-in t []) t)
+ (assert-not (pcall core.get-in))
+ (assert-not (pcall core.get-in {}))))
(deftest methods
(testing "methods"
- (defmulti f identity)
+ (defmulti f core.identity)
(defmethod f :a [_] :a)
(defmethod f :b [_] :b)
(defmethod f :c [x] (* x x))
- (assert-eq (methods f) f)
- (assert-not (pcall methods))
- (assert-not (pcall methods []))
- (assert-not (pcall methods f f)))
+ (assert-eq (core.methods f) f)
+ (assert-not (pcall core.methods))
+ (assert-not (pcall core.methods []))
+ (assert-not (pcall core.methods f f)))
(testing "get-method"
- (defmulti f identity)
+ (defmulti f core.identity)
(defmethod f :a [_] :a)
(defmethod f :b [_] :b)
(defmethod f :c [x] (* x x))
- (assert-eq ((get-method f :a) 10) :a)
- (assert-eq ((get-method f :b) 20) :b)
- (assert-eq ((get-method f :c) 4) 16)
- (assert-not (pcall get-method))
- (assert-not (pcall get-method []))
- (assert-not (pcall get-method [] :a))
- (assert-not (pcall get-method f))
- (assert-not (pcall get-method f :a :b)))
+ (assert-eq ((core.get-method f :a) 10) :a)
+ (assert-eq ((core.get-method f :b) 20) :b)
+ (assert-eq ((core.get-method f :c) 4) 16)
+ (assert-not (pcall core.get-method))
+ (assert-not (pcall core.get-method []))
+ (assert-not (pcall core.get-method [] :a))
+ (assert-not (pcall core.get-method f))
+ (assert-not (pcall core.get-method f :a :b)))
(testing "remove-method"
- (defmulti f identity)
+ (defmulti f core.identity)
(defmethod f :a [_] :a)
(defmethod f :b [_] :b)
- (remove-method f :a)
- (assert-eq (get-method f :a) nil)
+ (core.remove-method f :a)
+ (assert-eq (core.get-method f :a) nil)
(defmethod f :default [_] :default)
- (assert-eq (get-method f :a) (get-method f :default))
- (assert-not (pcall remove-method))
- (assert-not (pcall remove-method []))
- (assert-not (pcall remove-method [] :a))
- (assert-not (pcall remove-method f))
- (assert-not (pcall remove-method f :a :b)))
+ (assert-eq (core.get-method f :a) (core.get-method f :default))
+ (assert-not (pcall core.remove-method))
+ (assert-not (pcall core.remove-method []))
+ (assert-not (pcall core.remove-method [] :a))
+ (assert-not (pcall core.remove-method f))
+ (assert-not (pcall core.remove-method f :a :b)))
(testing "remove-all-methods"
- (defmulti f identity)
+ (defmulti f core.identity)
(defmethod f :a [_] :a)
(defmethod f :b [_] :b)
(defmethod f :default [_] :default)
- (remove-all-methods f)
- (assert-eq (methods f) {})
- (assert-not (pcall remove-all-methods))
- (assert-not (pcall remove-all-methods []))
- (assert-not (pcall remove-all-methods f f))))
+ (core.remove-all-methods f)
+ (assert-eq (core.methods f) {})
+ (assert-not (pcall core.remove-all-methods))
+ (assert-not (pcall core.remove-all-methods []))
+ (assert-not (pcall core.remove-all-methods f f))))
(deftest math-functions
- (testing "add"
- (assert-eq (add) 0)
- (assert-eq (add 1) 1)
- (assert-eq (add -1) -1)
- (assert-eq (add 1 2) 3)
- (assert-eq (add 1 2 3) 6)
- (assert-eq (add 1 2 3 4) 10)
- (assert-eq (add 1 2 3 4 5) 15))
+ (testing "core.add"
+ (assert-eq (core.add) 0)
+ (assert-eq (core.add 1) 1)
+ (assert-eq (core.add -1) -1)
+ (assert-eq (core.add 1 2) 3)
+ (assert-eq (core.add 1 2 3) 6)
+ (assert-eq (core.add 1 2 3 4) 10)
+ (assert-eq (core.add 1 2 3 4 5) 15))
(testing "sub"
- (assert-eq (sub) 0)
- (assert-eq (sub 1) -1)
- (assert-eq (sub -1) 1)
- (assert-eq (sub 1 2) -1)
- (assert-eq (sub 1 2 3) -4)
- (assert-eq (sub 1 2 3 4) -8)
- (assert-eq (sub 1 2 3 4 5) -13))
+ (assert-eq (core.sub) 0)
+ (assert-eq (core.sub 1) -1)
+ (assert-eq (core.sub -1) 1)
+ (assert-eq (core.sub 1 2) -1)
+ (assert-eq (core.sub 1 2 3) -4)
+ (assert-eq (core.sub 1 2 3 4) -8)
+ (assert-eq (core.sub 1 2 3 4 5) -13))
(testing "mul"
- (assert-eq (mul) 1)
- (assert-eq (mul 1) 1)
- (assert-eq (mul -1) -1)
- (assert-eq (mul 1 2) 2)
- (assert-eq (mul 1 2 3) 6)
- (assert-eq (mul 1 2 3 4) 24)
- (assert-eq (mul 1 2 3 4 5) 120))
+ (assert-eq (core.mul) 1)
+ (assert-eq (core.mul 1) 1)
+ (assert-eq (core.mul -1) -1)
+ (assert-eq (core.mul 1 2) 2)
+ (assert-eq (core.mul 1 2 3) 6)
+ (assert-eq (core.mul 1 2 3 4) 24)
+ (assert-eq (core.mul 1 2 3 4 5) 120))
(testing "div"
- (assert-not (pcall div))
- (assert-eq (div 1) 1)
- (assert-eq (div -1) -1)
- (assert-eq (div 1 2) (/ 1 2))
- (assert-eq (div 1 2 3) (/ 1 2 3))
- (assert-eq (div 1 2 3 4) (/ 1 2 3 4))
- (assert-eq (div 1 2 3 4 5) (/ 1 2 3 4 5))))
+ (assert-not (pcall core.div))
+ (assert-eq (core.div 1) 1)
+ (assert-eq (core.div -1) -1)
+ (assert-eq (core.div 1 2) (/ 1 2))
+ (assert-eq (core.div 1 2 3) (/ 1 2 3))
+ (assert-eq (core.div 1 2 3 4) (/ 1 2 3 4))
+ (assert-eq (core.div 1 2 3 4 5) (/ 1 2 3 4 5))))
(deftest comparison-functions
(testing "le"
- (assert-not (pcall le))
- (assert-is (le 1))
- (assert-is (le 1 2))
- (assert-is (le 1 2 2))
- (assert-is (le 1 2 3 4))
- (assert-not (le 2 1))
- (assert-not (le 2 1 3))
- (assert-not (le 1 2 4 3)))
+ (assert-not (pcall core.le))
+ (assert-is (core.le 1))
+ (assert-is (core.le 1 2))
+ (assert-is (core.le 1 2 2))
+ (assert-is (core.le 1 2 3 4))
+ (assert-not (core.le 2 1))
+ (assert-not (core.le 2 1 3))
+ (assert-not (core.le 1 2 4 3)))
(testing "lt"
- (assert-not (pcall lt))
- (assert-is (lt 1))
- (assert-is (lt 1 2))
- (assert-is (lt 1 2 3))
- (assert-is (lt 1 2 3 4))
- (assert-not (lt 2 1))
- (assert-not (lt 2 1 3))
- (assert-not (lt 1 2 4 4)))
+ (assert-not (pcall core.lt))
+ (assert-is (core.lt 1))
+ (assert-is (core.lt 1 2))
+ (assert-is (core.lt 1 2 3))
+ (assert-is (core.lt 1 2 3 4))
+ (assert-not (core.lt 2 1))
+ (assert-not (core.lt 2 1 3))
+ (assert-not (core.lt 1 2 4 4)))
(testing "ge"
- (assert-not (pcall ge))
- (assert-is (ge 2))
- (assert-is (ge 2 1))
- (assert-is (ge 3 3 2))
- (assert-is (ge 4 3 2 -1))
- (assert-not (ge 1 2))
- (assert-not (ge 2 1 3))
- (assert-not (ge 1 2 4 4)))
+ (assert-not (pcall core.ge))
+ (assert-is (core.ge 2))
+ (assert-is (core.ge 2 1))
+ (assert-is (core.ge 3 3 2))
+ (assert-is (core.ge 4 3 2 -1))
+ (assert-not (core.ge 1 2))
+ (assert-not (core.ge 2 1 3))
+ (assert-not (core.ge 1 2 4 4)))
(testing "gt"
- (assert-not (pcall gt))
- (assert-is (gt 2))
- (assert-is (gt 2 1))
- (assert-is (gt 3 2 1))
- (assert-is (gt 4 3 2 -1))
- (assert-not (gt 1 2))
- (assert-not (gt 2 1 3))
- (assert-not (gt 1 2 4 4))))
+ (assert-not (pcall core.gt))
+ (assert-is (core.gt 2))
+ (assert-is (core.gt 2 1))
+ (assert-is (core.gt 3 2 1))
+ (assert-is (core.gt 4 3 2 -1))
+ (assert-not (core.gt 1 2))
+ (assert-not (core.gt 2 1 3))
+ (assert-not (core.gt 1 2 4 4))))
(deftest vector
(testing "vector"
- (assert-eq (vector) [])
- (assert-eq (vector 1) [1])
- (assert-eq (vector 1 2 3) [1 2 3])
- (assert-eq (getmetatable (vector 1 2 3)) {:cljlib/type :seq})))
+ (assert-eq (core.vector) [])
+ (assert-eq (core.vector 1) [1])
+ (assert-eq (core.vector 1 2 3) [1 2 3])
+ (assert-eq (getmetatable (core.vector 1 2 3)) {:cljlib/type :seq})))
(deftest hash-map
(testing "hash-map"
- (assert-not (pcall hash-map :a))
- (assert-eq (hash-map) {})
- (assert-eq (hash-map :a 1) {:a 1})
- (assert-eq (hash-map :a 1 :b 2 :c 3) {:a 1 :b 2 :c 3})
- (assert-eq (getmetatable (hash-map)) {:cljlib/type :table})))
+ (assert-not (pcall core.hash-map :a))
+ (assert-eq (core.hash-map) {})
+ (assert-eq (core.hash-map :a 1) {:a 1})
+ (assert-eq (core.hash-map :a 1 :b 2 :c 3) {:a 1 :b 2 :c 3})
+ (assert-eq (getmetatable (core.hash-map)) {:cljlib/type :table})))
(deftest sets
(testing "hash-set"
- (let [h1 (hash-set [1] [1] [2] [3] [:a])
- h2 (hash-set [1] [2] [3] [:a])]
- (assert-is (eq h1 h2)))
+ (let [h1 (core.hash-set [1] [1] [2] [3] [:a])
+ h2 (core.hash-set [1] [2] [3] [:a])]
+ (assert-is (core.eq h1 h2)))
- (let [h3 (hash-set [1] [1] [2] [3] [:a])
- h4 (hash-set [1] [1] [3] [:a])]
- (assert-not (eq h3 h4)))
+ (let [h3 (core.hash-set [1] [1] [2] [3] [:a])
+ h4 (core.hash-set [1] [1] [3] [:a])]
+ (assert-not (core.eq h3 h4)))
- (assert-eq (. (hash-set [1]) [1]) [1])
- (assert-eq (. (hash-set [1]) [2]) nil)
- (assert-eq ((hash-set [1]) [1]) [1])
- (assert-eq ((hash-set [1]) [2]) nil))
+ (assert-eq (. (core.hash-set [1]) [1]) [1])
+ (assert-eq (. (core.hash-set [1]) [2]) nil)
+ (assert-eq ((core.hash-set [1]) [1]) [1])
+ (assert-eq ((core.hash-set [1]) [2]) nil))
(testing "ordered-set"
- (let [o1 (ordered-set [1] [1] [2] [3] [:a])
- o2 (ordered-set [1] [2] [3] [:a])]
+ (let [o1 (core.ordered-set [1] [1] [2] [3] [:a])
+ o2 (core.ordered-set [1] [2] [3] [:a])]
(assert-eq o1 o2))
- (let [o3 (ordered-set [1] [1] [2] [3] [:a])
- o4 (ordered-set [2] [1] [1] [3] [:a])]
+ (let [o3 (core.ordered-set [1] [1] [2] [3] [:a])
+ o4 (core.ordered-set [2] [1] [1] [3] [:a])]
(assert-eq o3 o4))
- (assert-eq (. (ordered-set [1]) [1]) [1])
- (assert-eq ((ordered-set [1]) [1]) [1])
- (assert-eq (. (ordered-set [1]) [2]) nil)
- (assert-eq ((ordered-set [1]) [2]) nil))
+ (assert-eq (. (core.ordered-set [1]) [1]) [1])
+ (assert-eq ((core.ordered-set [1]) [1]) [1])
+ (assert-eq (. (core.ordered-set [1]) [2]) nil)
+ (assert-eq ((core.ordered-set [1]) [2]) nil))
(testing "set equality"
- (let [o1 (ordered-set [1] [[-1 0] 1] [2] [3] [:a] :a 2)
- h1 (hash-set [1] [[-1 0] 1] [2] [3] [:a] :a 2)]
+ (let [o1 (core.ordered-set [1] [[-1 0] 1] [2] [3] [:a] :a 2)
+ h1 (core.hash-set [1] [[-1 0] 1] [2] [3] [:a] :a 2)]
(assert-eq o1 h1))
- (let [o2 (ordered-set [1] [[-1 0] 1] [2] [3] [:a] :a 2)
- h2 (hash-set [1] [[-1 1] 1] [2] [3] [:a] :a 2)]
+ (let [o2 (core.ordered-set [1] [[-1 0] 1] [2] [3] [:a] :a 2)
+ h2 (core.hash-set [1] [[-1 1] 1] [2] [3] [:a] :a 2)]
(assert-ne o2 h2))
- (let [o3 (ordered-set [1] [[-1 0] 1] [2] [3] [:a] :a 2)
- h3 (hash-set [1] [[-1 0] 1] [2] [3] [:a] :a 2)]
- (assert-eq (disj o3 [2]) (disj h3 [2]))
- (assert-ne (disj o3 :a) h3)
- (assert-eq (disj h3 :a) o3))
+ (let [o3 (core.ordered-set [1] [[-1 0] 1] [2] [3] [:a] :a 2)
+ h3 (core.hash-set [1] [[-1 0] 1] [2] [3] [:a] :a 2)]
+ (assert-eq (core.disj o3 [2]) (core.disj h3 [2]))
+ (assert-ne (core.disj o3 :a) h3)
+ (assert-eq (core.disj h3 :a) o3))
- (let [o4 (ordered-set [1] [[-1 5] 1] [3] [:a] :a 2)
- h4 (hash-set [1] [[-1 5] 1] [2] [3] [:a] :a 2)]
- (assert-eq (conj o4 [2]) (conj (disj h4 [2]) [2]))))
+ (let [o4 (core.ordered-set [1] [[-1 5] 1] [3] [:a] :a 2)
+ h4 (core.hash-set [1] [[-1 5] 1] [2] [3] [:a] :a 2)]
+ (assert-eq (core.conj o4 [2]) (core.conj (core.disj h4 [2]) [2]))))
(testing "empty sets"
- (assert-eq (empty (ordered-set)) (ordered-set))
- (assert-eq (empty (ordered-set 1 2 3)) (ordered-set))
- (assert-eq (. (getmetatable (empty (ordered-set))) :cljlib/type ) :cljlib/ordered-set)
+ (assert-eq (empty (core.ordered-set)) (core.ordered-set))
+ (assert-eq (empty (core.ordered-set 1 2 3)) (core.ordered-set))
+ (assert-eq (. (getmetatable (empty (core.ordered-set))) :cljlib/type ) :cljlib/ordered-set)
- (assert-eq (empty (hash-set)) (hash-set))
- (assert-eq (empty (hash-set 1 2 3)) (hash-set))
- (assert-eq (. (getmetatable (empty (hash-set))) :cljlib/type ) :cljlib/hash-set))
+ (assert-eq (empty (core.hash-set)) (core.hash-set))
+ (assert-eq (empty (core.hash-set 1 2 3)) (core.hash-set))
+ (assert-eq (. (getmetatable (empty (core.hash-set))) :cljlib/type ) :cljlib/hash-set))
(testing "into sets"
- (assert-eq (into (ordered-set) [1 2 3]) (ordered-set 1 2 3))
- (assert-eq (into (ordered-set) {:a 1 :b 2}) (ordered-set [:a 1] [:b 2]))
- (assert-eq (into (ordered-set) "vaiv") (ordered-set "v" "a" "i" "v"))
- (assert-eq (into (hash-set) [1 2 3]) (hash-set 1 2 3))
- (assert-eq (into (hash-set) {:a 1 :b 2}) (hash-set [:a 1] [:b 2]))
- (assert-eq (into (hash-set) "vaiv") (hash-set "v" "a" "i" "v"))))
+ (assert-eq (into (core.ordered-set) [1 2 3]) (core.ordered-set 1 2 3))
+ (assert-eq (into (core.ordered-set) {:a 1 :b 2}) (core.ordered-set [:a 1] [:b 2]))
+ (assert-eq (into (core.ordered-set) "vaiv") (core.ordered-set "v" "a" "i" "v"))
+ (assert-eq (into (core.hash-set) [1 2 3]) (core.hash-set 1 2 3))
+ (assert-eq (into (core.hash-set) {:a 1 :b 2}) (core.hash-set [:a 1] [:b 2]))
+ (assert-eq (into (core.hash-set) "vaiv") (core.hash-set "v" "a" "i" "v")))
+
+ (testing "sets into tables"
+ (assert-eq (into [] (core.ordered-set 1 2 3)) [1 2 3])
+ (assert-eq (into {} (core.ordered-set [:a 1] [:b 2])) {:a 1 :b 2})))
(deftest memoization
(testing "memoize"
@@ -801,10 +802,10 @@
(fn slow [x] (for [i 0 1000000] nil) x)
- (assert-not (pcall memoize))
- (assert-not (pcall memoize slow 2))
+ (assert-not (pcall core.memoize))
+ (assert-not (pcall core.memoize slow 2))
- (local fast (memoize slow))
+ (local fast (core.memoize slow))
(let [(res1 time1) (time (fast 42))
(res2 time2) (time (fast 42))]
@@ -813,5 +814,5 @@
(let [(res1 time1) (time (fast [10]))
(res2 time2) (time (fast [10]))]
- (assert-is (and (eq res1 res2 [10])))
+ (assert-is (and (core.eq res1 res2 [10])))
(assert-is (< time2 time1)))))
diff --git a/tests/fn.fnl b/tests/fn.fnl
index 4381a60..63a5802 100644
--- a/tests/fn.fnl
+++ b/tests/fn.fnl
@@ -1,5 +1,5 @@
(require-macros :tests.test)
-(require-macros :cljlib-macros)
+(require-macros :macros)
(deftest fn*
(testing "fn* meta"
@@ -7,7 +7,12 @@
"docstring"
[x] x)
(assert-eq (meta f) (when-meta {:fnl/docstring "docstring"
- :fnl/arglist ["[x]"]}))
+ :fnl/arglist ["([x])"]}))
+ (fn* f
+ "docstring"
+ [])
+ (assert-eq (meta f) (when-meta {:fnl/docstring "docstring"
+ :fnl/arglist ["([])"]}))
(fn* f
"docstring"
@@ -20,8 +25,16 @@
([x] x)
([x y] (+ x y)))
(assert-eq (meta f) (when-meta {:fnl/docstring "docstring"
- :fnl/arglist ["\n ([x])"
- "\n ([x y])"]}))
+ :fnl/arglist ["([x])"
+ "([x y])"]}))
+
+ (fn* f
+ "docstring"
+ ([])
+ ([x y] (+ x y)))
+ (assert-eq (meta f) (when-meta {:fnl/docstring "docstring"
+ :fnl/arglist ["([])"
+ "([x y])"]}))
(fn* f
"docstring"
@@ -29,6 +42,6 @@
([x y] (+ x y))
([x y & z] (+ x y)))
(assert-eq (meta f) (when-meta {:fnl/docstring "docstring"
- :fnl/arglist ["\n ([x])"
- "\n ([x y])"
- "\n ([x y & z])"]}))))
+ :fnl/arglist ["([x])"
+ "([x y])"
+ "([x y & z])"]}))))
diff --git a/tests/macros.fnl b/tests/macros.fnl
index e387eb2..c3b54c9 100644
--- a/tests/macros.fnl
+++ b/tests/macros.fnl
@@ -1,5 +1,5 @@
(require-macros :tests.test)
-(require-macros :cljlib-macros)
+(require-macros :macros)
(deftest into
(testing "into"
@@ -55,9 +55,9 @@
(let [a {}
b []]
(assert-eq (into a "vaiv") ["v" "a" "i" "v"])
- (assert-eq (into b "ваыв") ["в" "а" "ы" "в"]))
+ (when _G.utf8 (assert-eq (into b "ваыв") ["в" "а" "ы" "в"])))
(assert-eq (into [] "vaiv") ["v" "a" "i" "v"])
- (assert-eq (into [] "ваыв") ["в" "а" "ы" "в"])))
+ (when _G.utf8 (assert-eq (into [] "ваыв") ["в" "а" "ы" "в"]))))
(deftest let-variants
(testing "when-let"
@@ -89,7 +89,7 @@
(defmulti fac (fn [x] x))
(defmethod fac 0 [_] 1)
(defmethod fac :default [x] (* x (fac (- x 1))))
- (assert-eq (fac 42) 7538058755741581312))
+ (assert-eq (fac 4) 24))
(testing "defmulti keys"
(defmulti send-data (fn [protocol data] protocol))
@@ -212,13 +212,13 @@
(assert-eq (try (+ 1 2 3 nil) (catch _) (finally 10)) nil))
(testing "catch-all"
(assert-eq (try
- (error 10)
- (catch _ :pass))
- :pass)
+ (error "10")
+ (catch _ :pass))
+ :pass)
(assert-eq (try
- (error 10)
- (catch err err))
- 10))
+ (error [10])
+ (catch err err))
+ [10]))
(testing "finally"
(let [tbl []]
(try
diff --git a/tests/test.fnl b/tests/test.fnl
index f3db701..143b749 100644
--- a/tests/test.fnl
+++ b/tests/test.fnl
@@ -14,12 +14,12 @@ the tables uses tables as keys."
;; (eq {[1 2 3] {:a [1 2 3]}} {[1 2 3] {:a [1 2 3]}})
;; we have to do even deeper search
(setmetatable right# {:__index (fn [tbl# key#]
- (var res# nil)
- (each [k# v# (pairs tbl#)]
- (when (eq# k# key#)
- (set res# v#)
- (lua :break)))
- res#)})
+ (var res# nil)
+ (each [k# v# (pairs tbl#)]
+ (when (eq# k# key#)
+ (set res# v#)
+ (lua :break)))
+ res#)})
(var [res# count-a# count-b#] [true 0 0])
(each [k# v# (pairs left#)]
(set res# (eq# v# (. right# k#)))
@@ -62,26 +62,26 @@ runtime error: equality assertion failed
```"
`(let [left# ,expr1
right# ,expr2
- (res# view#) (pcall require :fennelview)
eq# ,(eq-fn)
- tostr# (if res# view# tostring)]
+ fennel# (require :fennel)]
(assert (eq# left# right#)
- (or ,msg (.. "equality assertion failed
- Left: " (tostr# left#) "
- Right: " (tostr# right#) "\n")))))
+ (or ,msg (.. "assertion failed for expression:
+(= " ,(view expr1 {:one-line? true}) " " ,(view expr2 {:one-line? true}) "
+ Left: " (fennel#.view left# {:one-line? true}) "
+ Right: " (fennel#.view right# {:one-line? true}) "\n")))))
(fn test.assert-ne
[expr1 expr2 msg]
"Assert for unequality. Same as [`assert-eq`](#assert-eq)."
`(let [left# ,expr1
right# ,expr2
- (res# view#) (pcall require :fennelview)
eq# ,(eq-fn)
- tostr# (if res# view# tostring)]
+ fennel# (require :fennel)]
(assert (not (eq# left# right#))
- (or ,msg (.. "unequality assertion failed
- Left: " (tostr# left#) "
- Right: " (tostr# right#) "\n")))))
+ (or ,msg (.. "assertion failed for expression:
+(not= " ,(view expr1 {:one-line? true}) " " ,(view expr2 {:one-line? true}) "
+ Left: " (fennel#.view left# {:one-line? true}) "
+ Right: " (fennel#.view right# {:one-line? true}) "\n")))))
(fn test.assert-is
[expr msg]
@@ -92,13 +92,15 @@ runtime error: equality assertion failed
>> (assert-is (= 1 2 3))
runtime error: assertion failed for (= 1 2 3)
```"
- `(assert ,expr (.. "assertion failed for "
- (or ,msg ,(tostring expr)))))
+ `(assert ,expr
+ (.. "assertion failed for "
+ (or ,msg ,(view expr {:one-line? true})))))
(fn test.assert-not
[expr msg]
"Assert for not truth. Works the same as [`assert-is`](#assert-is)."
- `(assert (not ,expr) (.. "assertion failed for "
- (or ,msg ,(tostring expr)))))
+ `(assert (not ,expr)
+ (.. "assertion failed for "
+ (or ,msg ,(view expr {:one-line? true})))))
(fn test.deftest
[name ...]
@@ -108,7 +110,7 @@ runtime error: assertion failed for (= 1 2 3)
(fn test.testing
[description ...]
"Print test description and run it."
- `(do (io.stderr:write (.. "testing: " ,description "\n"))
+ `(do (io.stdout:write (.. "testing: " ,description "\n"))
,...))
(doto test