From 0549b1e5a8a3132005e275d6026db8003cb067d2 Mon Sep 17 00:00:00 2001 From: chai Date: Tue, 26 Oct 2021 11:32:46 +0800 Subject: *rename folder --- Data/DefaultContent/Libraries/luafun/.gitignore | 4 + Data/DefaultContent/Libraries/luafun/.travis.yml | 74 ++ .../Libraries/luafun/CONTRIBUTING.md | 20 + Data/DefaultContent/Libraries/luafun/COPYING.md | 27 + Data/DefaultContent/Libraries/luafun/README.md | 107 ++ .../Libraries/luafun/debian/.gitignore | 8 + .../Libraries/luafun/debian/changelog | 5 + Data/DefaultContent/Libraries/luafun/debian/compat | 1 + .../DefaultContent/Libraries/luafun/debian/control | 20 + .../Libraries/luafun/debian/copyright | 31 + .../Libraries/luafun/debian/lua-fun.docs | 1 + .../Libraries/luafun/debian/lua5.1.dh-lua.conf | 4 + .../Libraries/luafun/debian/lua5.2.dh-lua.conf | 1 + .../Libraries/luafun/debian/lua5.3.dh-lua.conf | 1 + .../Libraries/luafun/debian/patches/series | 0 Data/DefaultContent/Libraries/luafun/debian/rules | 12 + .../Libraries/luafun/debian/source/format | 1 + Data/DefaultContent/Libraries/luafun/debian/watch | 6 + .../DefaultContent/Libraries/luafun/doc/.gitignore | 1 + Data/DefaultContent/Libraries/luafun/doc/Makefile | 153 +++ .../Libraries/luafun/doc/_static/.keep | 0 .../Libraries/luafun/doc/_templates/layout.html | 14 + Data/DefaultContent/Libraries/luafun/doc/about.rst | 42 + Data/DefaultContent/Libraries/luafun/doc/basic.rst | 141 +++ .../Libraries/luafun/doc/compositions.rst | 140 +++ Data/DefaultContent/Libraries/luafun/doc/conf.py | 247 +++++ .../Libraries/luafun/doc/filtering.rst | 121 +++ .../Libraries/luafun/doc/generators.rst | 233 +++++ .../Libraries/luafun/doc/getting_started.rst | 254 +++++ Data/DefaultContent/Libraries/luafun/doc/index.rst | 29 + .../Libraries/luafun/doc/indexing.rst | 74 ++ Data/DefaultContent/Libraries/luafun/doc/intro.rst | 69 ++ Data/DefaultContent/Libraries/luafun/doc/logo.png | Bin 0 -> 14370 bytes Data/DefaultContent/Libraries/luafun/doc/logo.svg | 758 ++++++++++++++ Data/DefaultContent/Libraries/luafun/doc/make.bat | 190 ++++ .../Libraries/luafun/doc/operators.rst | 203 ++++ .../Libraries/luafun/doc/reducing.rst | 323 ++++++ .../Libraries/luafun/doc/reference.rst | 14 + .../Libraries/luafun/doc/slicing.rst | 246 +++++ .../Libraries/luafun/doc/transformations.rst | 87 ++ .../Libraries/luafun/doc/under_the_hood.rst | 154 +++ .../Libraries/luafun/fun-scm-1.rockspec | 34 + Data/DefaultContent/Libraries/luafun/fun.lua | 1058 ++++++++++++++++++++ .../Libraries/luafun/rpm/lua-fun.spec | 76 ++ .../Libraries/luafun/tests/.gitignore | 1 + .../Libraries/luafun/tests/basic.lua | 332 ++++++ .../Libraries/luafun/tests/compositions.lua | 170 ++++ .../Libraries/luafun/tests/filtering.lua | 102 ++ .../Libraries/luafun/tests/generators.lua | 287 ++++++ .../Libraries/luafun/tests/indexing.lua | 83 ++ .../Libraries/luafun/tests/operators.lua | 322 ++++++ .../Libraries/luafun/tests/reducing.lua | 289 ++++++ Data/DefaultContent/Libraries/luafun/tests/runtest | 114 +++ .../Libraries/luafun/tests/slicing.lua | 339 +++++++ .../Libraries/luafun/tests/transformations.lua | 107 ++ 55 files changed, 7130 insertions(+) create mode 100644 Data/DefaultContent/Libraries/luafun/.gitignore create mode 100644 Data/DefaultContent/Libraries/luafun/.travis.yml create mode 100644 Data/DefaultContent/Libraries/luafun/CONTRIBUTING.md create mode 100644 Data/DefaultContent/Libraries/luafun/COPYING.md create mode 100644 Data/DefaultContent/Libraries/luafun/README.md create mode 100644 Data/DefaultContent/Libraries/luafun/debian/.gitignore create mode 100644 Data/DefaultContent/Libraries/luafun/debian/changelog create mode 100644 Data/DefaultContent/Libraries/luafun/debian/compat create mode 100644 Data/DefaultContent/Libraries/luafun/debian/control create mode 100644 Data/DefaultContent/Libraries/luafun/debian/copyright create mode 100644 Data/DefaultContent/Libraries/luafun/debian/lua-fun.docs create mode 100644 Data/DefaultContent/Libraries/luafun/debian/lua5.1.dh-lua.conf create mode 100644 Data/DefaultContent/Libraries/luafun/debian/lua5.2.dh-lua.conf create mode 100644 Data/DefaultContent/Libraries/luafun/debian/lua5.3.dh-lua.conf create mode 100644 Data/DefaultContent/Libraries/luafun/debian/patches/series create mode 100644 Data/DefaultContent/Libraries/luafun/debian/rules create mode 100644 Data/DefaultContent/Libraries/luafun/debian/source/format create mode 100644 Data/DefaultContent/Libraries/luafun/debian/watch create mode 100644 Data/DefaultContent/Libraries/luafun/doc/.gitignore create mode 100644 Data/DefaultContent/Libraries/luafun/doc/Makefile create mode 100644 Data/DefaultContent/Libraries/luafun/doc/_static/.keep create mode 100644 Data/DefaultContent/Libraries/luafun/doc/_templates/layout.html create mode 100644 Data/DefaultContent/Libraries/luafun/doc/about.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/basic.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/compositions.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/conf.py create mode 100644 Data/DefaultContent/Libraries/luafun/doc/filtering.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/generators.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/getting_started.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/index.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/indexing.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/intro.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/logo.png create mode 100644 Data/DefaultContent/Libraries/luafun/doc/logo.svg create mode 100644 Data/DefaultContent/Libraries/luafun/doc/make.bat create mode 100644 Data/DefaultContent/Libraries/luafun/doc/operators.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/reducing.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/reference.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/slicing.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/transformations.rst create mode 100644 Data/DefaultContent/Libraries/luafun/doc/under_the_hood.rst create mode 100644 Data/DefaultContent/Libraries/luafun/fun-scm-1.rockspec create mode 100644 Data/DefaultContent/Libraries/luafun/fun.lua create mode 100644 Data/DefaultContent/Libraries/luafun/rpm/lua-fun.spec create mode 100644 Data/DefaultContent/Libraries/luafun/tests/.gitignore create mode 100644 Data/DefaultContent/Libraries/luafun/tests/basic.lua create mode 100644 Data/DefaultContent/Libraries/luafun/tests/compositions.lua create mode 100644 Data/DefaultContent/Libraries/luafun/tests/filtering.lua create mode 100644 Data/DefaultContent/Libraries/luafun/tests/generators.lua create mode 100644 Data/DefaultContent/Libraries/luafun/tests/indexing.lua create mode 100644 Data/DefaultContent/Libraries/luafun/tests/operators.lua create mode 100644 Data/DefaultContent/Libraries/luafun/tests/reducing.lua create mode 100644 Data/DefaultContent/Libraries/luafun/tests/runtest create mode 100644 Data/DefaultContent/Libraries/luafun/tests/slicing.lua create mode 100644 Data/DefaultContent/Libraries/luafun/tests/transformations.lua (limited to 'Data/DefaultContent/Libraries/luafun') diff --git a/Data/DefaultContent/Libraries/luafun/.gitignore b/Data/DefaultContent/Libraries/luafun/.gitignore new file mode 100644 index 0000000..0ebe4e1 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/.gitignore @@ -0,0 +1,4 @@ +*~ +temp/ +fun.lua.c +5.?-fun/ diff --git a/Data/DefaultContent/Libraries/luafun/.travis.yml b/Data/DefaultContent/Libraries/luafun/.travis.yml new file mode 100644 index 0000000..2c3f4d8 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/.travis.yml @@ -0,0 +1,74 @@ +sudo: false +language: C +services: + - docker + +env: + global: + - PRODUCT=lua-fun + matrix: + - OS=el DIST=7 + - OS=fedora DIST=24 + - OS=fedora DIST=25 + - OS=ubuntu DIST=xenial + - OS=ubuntu DIST=yakkety + - OS=debian DIST=stretch + +before_deploy: + - git clone https://github.com/packpack/packpack.git packpack + - ./packpack/packpack + +deploy: + provider: packagecloud + username: ${PACKAGECLOUD_USER} + repository: ${PACKAGECLOUD_REPO} + token: ${PACKAGECLOUD_TOKEN} + dist: ${OS}/${DIST} + package_glob: build/*.{deb,rpm} + skip_cleanup: true + on: + branch: master + condition: -n "${OS}" && -n "${DIST}" && -n "${PACKAGECLOUD_TOKEN}" + +after_deploy: + # Prune old packages from PackageCloud, keep only the last two + - pip install -r ./packpack/tools/requirements.txt + - python ./packpack/tools/packagecloud prune ${PACKAGECLOUD_USER}/${PACKAGECLOUD_REPO} deb ${OS} ${DIST} --keep 2 + - python ./packpack/tools/packagecloud prune ${PACKAGECLOUD_USER}/${PACKAGECLOUD_REPO} rpm ${OS} ${DIST} --keep 2 + +cache: + directories: + - $HOME/lua-5.3.2 + +addons: + apt: + packages: + - lua5.1 + - lua5.2 + - luajit + +# Ubuntu Precise on Travis doesn't have lua5.3 package +install: + - | + [ -e ${HOME}/lua-5.3.2/src/lua ] || (\ + wget http://www.lua.org/ftp/lua-5.3.2.tar.gz -c && \ + tar xzf lua-5.3.2.tar.gz -C ${HOME} && \ + make -j -C ${HOME}/lua-5.3.2 linux \ + ) + +script: + - cd tests + - LUAJIT=`echo /usr/bin/luajit* | cut -f 1 -d ' '` + - ${LUAJIT} -v + - ${LUAJIT} runtest *.lua + - lua5.1 -v + - lua5.1 runtest *.lua + - lua5.2 -v + - lua5.2 runtest *.lua + - LUA53=${HOME}/lua-5.3.2/src/lua + - ${LUA53} -v + - ${LUA53} runtest *.lua + - cd .. + +notifications: + email: true diff --git a/Data/DefaultContent/Libraries/luafun/CONTRIBUTING.md b/Data/DefaultContent/Libraries/luafun/CONTRIBUTING.md new file mode 100644 index 0000000..660ec53 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/CONTRIBUTING.md @@ -0,0 +1,20 @@ +Contributing +============ + +We'd love for you to contribute to the project and make **Lua Fun** even better +than it is today! + +Filling Issues +--------------- + +Please file bugs reports and feature requests using [GitHub Issues]. + +[GitHub Issues]: https://github.com/luafun/luafun/issues + +Making Changes +-------------- + +If you want to contribute code, please fork the project on [GitHub], make +changes in branch and send a pull request. + +[GitHub]: https://github.com/luafun/luafun diff --git a/Data/DefaultContent/Libraries/luafun/COPYING.md b/Data/DefaultContent/Libraries/luafun/COPYING.md new file mode 100644 index 0000000..c945d62 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/COPYING.md @@ -0,0 +1,27 @@ +Copying +======= + +**Lua Fun** source codes, logo and documentation are distributed under the +**[MIT/X11 License]** - same as Lua and LuaJIT. + +Copyright (c) 2013-2017 Roman Tsisyk + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +[MIT/X11 License]: http://www.opensource.org/licenses/mit-license.php diff --git a/Data/DefaultContent/Libraries/luafun/README.md b/Data/DefaultContent/Libraries/luafun/README.md new file mode 100644 index 0000000..c7a2d61 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/README.md @@ -0,0 +1,107 @@ +Lua Functional +============== + + + +**Lua Fun** is a high-performance functional programming library for [Lua] +designed with [LuaJIT's trace compiler][LuaJIT] in mind. + +Lua Fun provides a set of more than 50 programming primitives typically +found in languages like Standard ML, Haskell, Erlang, JavaScript, Python and +even Lisp. High-order functions such as ``map``, ``filter``, ``reduce``, +``zip``, etc., make it easy to **write simple and efficient functional code**. + +Let's see an example: + + > -- Functional style + > require "fun" () + > -- calculate sum(x for x^2 in 1..n) + > n = 100 + > print(reduce(operator.add, 0, map(function(x) return x^2 end, range(n)))) + 328350 + + > -- Object-oriented style + > local fun = require "fun" + > -- calculate sum(x for x^2 in 1..n) + > print(fun.range(n):map(function(x) return x^2 end):reduce(operator.add, 0)) + 328350 + +**Lua Fun** takes full advantage of the innovative **tracing JIT compiler** +to achieve transcendental performance on nested functional expressions. +Functional compositions and high-order functions can be translated into +**efficient machine code**. Can you believe it? Just try to run the example +above with ``luajit -jdump`` and see what happens: + + -- skip some initilization code -- + ->LOOP: + 0bcaffd0 movaps xmm5, xmm7 + 0bcaffd3 movaps xmm7, xmm1 + 0bcaffd6 addsd xmm7, xmm5 + 0bcaffda ucomisd xmm7, xmm0 + 0bcaffde jnb 0x0bca0024 ->5 + 0bcaffe4 movaps xmm5, xmm7 + 0bcaffe7 mulsd xmm5, xmm5 + 0bcaffeb addsd xmm6, xmm5 + 0bcaffef jmp 0x0bcaffd0 ->LOOP + ---- TRACE 1 stop -> loop + +The functional chain above was translated by LuaJIT to (!) **one machine loop** +containing just 10 CPU assembly instructions without CALL. Unbelievable! + +Readable? Efficient? Can your Python/Ruby/V8 do better? + +Status +------ + +**Lua Fun** is in an early alpha stage. The library fully [documented] +[Documentation] and covered with unit tests. + +[![Build Status](https://travis-ci.org/luafun/luafun.png)] +(https://travis-ci.org/luafun/luafun) + +LuaJIT 2.1 alpha is recommended. The library designed in mind of fact that +[LuaJIT traces tail-, up- and down-recursion][LuaJIT-Recursion] and has a lot of +[byte code optimizations][LuaJIT-Optimizations]. Lua 5.1-5.3 are also +supported. + +This is **master** (development) branch. API may be changed without any special +notice. Please use **stable** branch for your production deployments. +If you still want to use **master**, please don't forget to grep `git log` +for *Incompatible API changes* message. Thanks! + +Please check out [documentation][Documentation] for more information. + +Misc +---- + +**Lua Fun** is distributed under the [MIT/X11 License] - +(same as Lua and LuaJIT). + +The library was written to use with [Tarantool] - an efficient in-memory +store and an asynchronous Lua application server. + +See Also +-------- + +* [Documentation] +* [RockSpec] +* [RPM/DEB packages](https://packagecloud.io/rtsisyk/master) +* lua-l@lists.lua.org +* luajit@freelists.org +* roman@tsisyk.com + + [Lua]: http://www.lua.org/ + [LuaJIT]: http://luajit.org/luajit.html + [LuaJIT-Recursion]: http://lambda-the-ultimate.org/node/3851#comment-57679 + [LuaJIT-Optimizations]: http://wiki.luajit.org/Optimizations + [MIT/X11 License]: http://opensource.org/licenses/MIT + [Tarantool]: http://github.com/tarantool/tarantool + [Getting Started]: https://luafun.github.io/getting_started.html + [Documentation]: http://luafun.github.io/ + [RockSpec]: https://raw.github.com/luafun/luafun/master/fun-scm-1.rockspec + +Please **"Star"** the project on GitHub to help it to survive! Thanks! + +***** + +**Lua Fun**. Simple, Efficient and Functional. In Lua. With JIT. diff --git a/Data/DefaultContent/Libraries/luafun/debian/.gitignore b/Data/DefaultContent/Libraries/luafun/debian/.gitignore new file mode 100644 index 0000000..aa3e6bf --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/debian/.gitignore @@ -0,0 +1,8 @@ +lua-fun/ +tmp/ +trash +files +lua_versions +*.install +*.substvars +*.log diff --git a/Data/DefaultContent/Libraries/luafun/debian/changelog b/Data/DefaultContent/Libraries/luafun/debian/changelog new file mode 100644 index 0000000..262c02d --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/debian/changelog @@ -0,0 +1,5 @@ +lua-fun (0.1.3-1) unstable; urgency=medium + + * Initial release. (Closes: #811482) + + -- Roman Tsisyk Mon, 18 Jan 2016 10:00:00 +0300 diff --git a/Data/DefaultContent/Libraries/luafun/debian/compat b/Data/DefaultContent/Libraries/luafun/debian/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/debian/compat @@ -0,0 +1 @@ +9 diff --git a/Data/DefaultContent/Libraries/luafun/debian/control b/Data/DefaultContent/Libraries/luafun/debian/control new file mode 100644 index 0000000..f93b318 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/debian/control @@ -0,0 +1,20 @@ +Source: lua-fun +Section: interpreters +Priority: optional +Maintainer: Roman Tsisyk +Build-Depends: debhelper (>= 9), dh-lua (>= 19) +Standards-Version: 3.9.6 +Homepage: https://github.com/luafun/luafun +Vcs-Git: git://github.com/luafun/luafun.git +Vcs-Browser: https://github.com/luafun/luafun + +Package: lua-fun +Architecture: all +Depends: ${misc:Depends} +Provides: ${lua:Provides} +XB-Lua-Versions: ${lua:Versions} +Description: High-performance functional programming library for Lua + Lua Fun provides a set of more than 50 programming primitives typically + found in languages like Standard ML, Haskell, Erlang, JavaScript, Python and + even Lisp. High-order functions such as map, filter, reduce, zip, etc., + make it easy to write simple and efficient functional code. diff --git a/Data/DefaultContent/Libraries/luafun/debian/copyright b/Data/DefaultContent/Libraries/luafun/debian/copyright new file mode 100644 index 0000000..34f24ad --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/debian/copyright @@ -0,0 +1,31 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: luafun +Upstream-Contact: Roman Tsisyk +Source: https://github.com/luafun/luafun + +Files: * +Copyright: 2013-2017 Roman Tsisyk +Comment: In the Lua community this license is better known as "MIT". + Unfortunately other variants of this license are also known as "MIT". + To obtain a machine intepretable copyright file Debian prefers to name this + version of the MIT license using the non ambiguous term "Expat". +License: Expat + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + “Software”), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + . + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. diff --git a/Data/DefaultContent/Libraries/luafun/debian/lua-fun.docs b/Data/DefaultContent/Libraries/luafun/debian/lua-fun.docs new file mode 100644 index 0000000..b43bf86 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/debian/lua-fun.docs @@ -0,0 +1 @@ +README.md diff --git a/Data/DefaultContent/Libraries/luafun/debian/lua5.1.dh-lua.conf b/Data/DefaultContent/Libraries/luafun/debian/lua5.1.dh-lua.conf new file mode 100644 index 0000000..fa57bb6 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/debian/lua5.1.dh-lua.conf @@ -0,0 +1,4 @@ +PKG_NAME=fun +LUA_MODNAME=fun +LUA_SOURCES=fun.lua +LUA_TEST=tests/runtest tests/*.lua diff --git a/Data/DefaultContent/Libraries/luafun/debian/lua5.2.dh-lua.conf b/Data/DefaultContent/Libraries/luafun/debian/lua5.2.dh-lua.conf new file mode 100644 index 0000000..ba875b6 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/debian/lua5.2.dh-lua.conf @@ -0,0 +1 @@ +lua5.1.dh-lua.conf \ No newline at end of file diff --git a/Data/DefaultContent/Libraries/luafun/debian/lua5.3.dh-lua.conf b/Data/DefaultContent/Libraries/luafun/debian/lua5.3.dh-lua.conf new file mode 100644 index 0000000..ba875b6 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/debian/lua5.3.dh-lua.conf @@ -0,0 +1 @@ +lua5.1.dh-lua.conf \ No newline at end of file diff --git a/Data/DefaultContent/Libraries/luafun/debian/patches/series b/Data/DefaultContent/Libraries/luafun/debian/patches/series new file mode 100644 index 0000000..e69de29 diff --git a/Data/DefaultContent/Libraries/luafun/debian/rules b/Data/DefaultContent/Libraries/luafun/debian/rules new file mode 100644 index 0000000..9e473ed --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/debian/rules @@ -0,0 +1,12 @@ +#!/usr/bin/make -f + +VERSION := $(shell dpkg-parsechangelog|grep ^Version|awk '{print $$2}') +UVERSION := $(shell echo $(VERSION)|sed 's/-[[:digit:]]\+$$//') + +%: + dh $@ --buildsystem=lua --with lua + +tarball: clean + tar --exclude=.git --exclude=debian --exclude rpm \ + --transform='s,^\.,luafun-$(UVERSION),S' \ + -czf ../luafun-$(UVERSION).orig.tar.gz . diff --git a/Data/DefaultContent/Libraries/luafun/debian/source/format b/Data/DefaultContent/Libraries/luafun/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/Data/DefaultContent/Libraries/luafun/debian/watch b/Data/DefaultContent/Libraries/luafun/debian/watch new file mode 100644 index 0000000..40bc2ca --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/debian/watch @@ -0,0 +1,6 @@ +# test this watch file using: +# uscan --watchfile debian/watch --upstream-version 0.0.1 --package lua-fun +# https://wiki.debian.org/debian/watch#GitHub +version=3 +opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/luafun-$1\.tar\.gz/ \ + https://github.com/luafun/luafun/tags .*/v?(\d\S*)\.tar\.gz diff --git a/Data/DefaultContent/Libraries/luafun/doc/.gitignore b/Data/DefaultContent/Libraries/luafun/doc/.gitignore new file mode 100644 index 0000000..e35d885 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/.gitignore @@ -0,0 +1 @@ +_build diff --git a/Data/DefaultContent/Libraries/luafun/doc/Makefile b/Data/DefaultContent/Libraries/luafun/doc/Makefile new file mode 100644 index 0000000..1e1b049 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/Makefile @@ -0,0 +1,153 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/LuaFunctional.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/LuaFunctional.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/LuaFunctional" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/LuaFunctional" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/Data/DefaultContent/Libraries/luafun/doc/_static/.keep b/Data/DefaultContent/Libraries/luafun/doc/_static/.keep new file mode 100644 index 0000000..e69de29 diff --git a/Data/DefaultContent/Libraries/luafun/doc/_templates/layout.html b/Data/DefaultContent/Libraries/luafun/doc/_templates/layout.html new file mode 100644 index 0000000..ee1fa29 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/_templates/layout.html @@ -0,0 +1,14 @@ +{% extends "!layout.html" %} + +{% block footer %} +{{ super() }} + +{% endblock %} diff --git a/Data/DefaultContent/Libraries/luafun/doc/about.rst b/Data/DefaultContent/Libraries/luafun/doc/about.rst new file mode 100644 index 0000000..97da8dc --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/about.rst @@ -0,0 +1,42 @@ +About +===== + +Credits +------- + +An initial prototype was designed and enginered in one evening by Roman Tsisyk. +After that the library was completely rewritten, tested and documented +(which took a while). + +The project exists only thanks to the excellent tracing just-in-time compiler +in `LuaJIT `_. + +The library works best with `Tarantool `_ -- +an efficient in-memory database and Lua application server. + +Copying +------- + +Lua Fun source codes, logo and documentation are distributed under the +`MIT License (MIT) `_ -- +same as LuaJIT. + +Copyright (c) 2013-2017 Roman Tsisyk + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Data/DefaultContent/Libraries/luafun/doc/basic.rst b/Data/DefaultContent/Libraries/luafun/doc/basic.rst new file mode 100644 index 0000000..346dd78 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/basic.rst @@ -0,0 +1,141 @@ +Basic Functions +=============== + +.. module:: fun + +The section contains functions to create iterators from Lua objects. + +.. function:: iter(array) + iter(map) + iter(string) + iter(gen, param, state) + + :returns: ``gen, param, state`` -- :ref:`iterator triplet ` + + Make ``gen, param, state`` iterator from the iterable object. + The function is a generalized version of :func:`pairs` and :func:`ipairs`. + + The function distinguish between arrays and maps using ``#arg == 0`` + check to detect maps. For arrays ``ipairs`` is used. For maps a modified + version of ``pairs`` is used that also returns keys. Userdata objects + are handled in the same way as tables. + + If ``LUAJIT_ENABLE_LUA52COMPAT`` [#luajit_lua52compat]_ mode is enabled and + argument has metamethods ``__pairs`` (for maps) or ``__ipairs`` for (arrays), + call it with the table or userdata as argument and return the first three + results from the call [#lua52_ipairs]_. + + All library iterator are suitable to use with Lua's ``for .. in`` loop. + + .. code-block:: lua + + > for _it, a in iter({1, 2, 3}) do print(a) end + 1 + 2 + 3 + + > for _it, k, v in iter({ a = 1, b = 2, c = 3}) do print(k, v) end + b 2 + a 1 + c 3 + + > for _it, a in iter("abcde") do print(a) end + a + b + c + d + e + + The first cycle variable *_it* is needed to store an internal state of + the iterator. The value must be always ignored in loops: + + .. code-block:: lua + + for _it, a, b in iter({ a = 1, b = 2, c = 3}) do print(a, b) end + -- _it is some internal iterator state - always ignore it + -- a, b are values return from the iterator + + Simple iterators like ``iter({1, 2, 3})`` have simple states, whereas + other iterators like :func:`zip` or :func:`chain` have complicated + internal states which values senseless for the end user. + + Check out :doc:`under_the_hood` section for more details. + + There is also the possibility to supply custom iterators to the + function: + + .. code-block:: lua + + > local function mypairs_gen(max, state) + if (state >= max) then + return nil + end + return state + 1, state + 1 + end + + > local function mypairs(max) + return mypairs_gen, max, 0 + end + + > for _it, a in iter(mypairs(10)) do print(a) end + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + + Iterators can return multiple values. + + Check out :doc:`under_the_hood` section for more details. + + .. [#luajit_lua52compat] http://luajit.org/extensions.html + .. [#lua52_ipairs] http://www.lua.org/manual/5.2/manual.html#pdf-ipairs + +.. function:: each(fun, gen, param, state) + iterator:each(fun) + + :returns: none + + Execute the *fun* for each iteration value. The function is equivalent to + the code below: + + .. code-block:: lua + + for _it, ... in iter(gen, param, state) do + fun(...) + end + + Examples: + + .. code-block:: lua + + > each(print, { a = 1, b = 2, c = 3}) + b 2 + a 1 + c 3 + + > each(print, {1, 2, 3}) + 1 + 2 + 3 + + The function is used for its side effects. Implementation directly applies + *fun* to all iteration values without returning a new iterator, in contrast + to functions like :func:`map`. + + .. seealso:: :func:`map`, :func:`reduce` + +.. function:: for_each(fun, gen, param, state) + iterator:for_each(fun) + + An alias for :func:`each`. + +.. function:: foreach(fun, gen, param, state) + iterator:foreach(fun) + + An alias for :func:`each`. diff --git a/Data/DefaultContent/Libraries/luafun/doc/compositions.rst b/Data/DefaultContent/Libraries/luafun/doc/compositions.rst new file mode 100644 index 0000000..4c789b3 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/compositions.rst @@ -0,0 +1,140 @@ +Compositions +============ + +.. module:: fun + +.. function:: zip(...) + iterator1:zip(iterator2, iterator3, ...) + + :param ...: iterators to "zip" + :type ...: iterator + + :returns: an iterator + + Return a new iterator where i-th return value contains the i-th element + from each of the iterators. The returned iterator is truncated in length + to the length of the shortest iterator. For multi-return iterators only the + first variable is used. + + Examples: + + .. code-block:: lua + + > dump(zip({"a", "b", "c", "d"}, {"one", "two", "three"})) + a one + b two + c three + + > each(print, zip()) + + > each(print, zip(range(5), {'a', 'b', 'c'}, rands())) + 1 a 0.57514179487402 + 2 b 0.79693061238668 + 3 c 0.45174307459403 + + > each(print, zip(partition(function(x) return x > 7 end, range(1, 15, 1)))) + 8 1 + 9 2 + 10 3 + 11 4 + 12 5 + 13 6 + 14 7 + +.. function:: cycle(gen, param, state) + iterator:cycle() + + :returns: a cycled version of ``{gen, param, state}`` iterator + + Make a new iterator that returns elements from ``{gen, param, state}`` + iterator until the end and then "restart" iteration using a saved clone of + ``{gen, param, state}``. The returned iterator is constant space and no + return values are buffered. Instead of that the function make a clone of the + source ``{gen, param, state}`` iterator. Therefore, the source iterator + must be pure functional to make an indentical clone. Infinity iterators + are supported, but are not recommended. + + .. note:: ``{gen, param, state}`` must be pure functional to work properly + with the function. + + Examples: + + .. code-block:: lua + + > each(print, take(15, cycle(range(5)))) + 1 + 2 + 3 + 4 + 5 + 1 + 2 + 3 + 4 + 5 + 1 + 2 + 3 + 4 + 5 + + > each(print, take(15, cycle(zip(range(5), {"a", "b", "c", "d", "e"})))) + 1 a + 2 b + 3 c + 4 d + 5 e + 1 a + 2 b + 3 c + 4 d + 5 e + 1 a + 2 b + 3 c + 4 d + 5 e + +.. function:: chain(...) + iterator1:chain(iterator2, iterator3, ...) + + :param ...: iterators to chain + :type ...: iterator + :returns: a consecutive iterator from sources (left from right) + + Make an iterator that returns elements from the first iterator until it is + exhausted, then proceeds to the next iterator, until all of the iterators + are exhausted. Used for treating consecutive iterators as a single iterator. + Infinity iterators are supported, but are not recommended. + + Examples: + + .. code-block:: lua + + > each(print, chain(range(2), {"a", "b", "c"}, {"one", "two", "three"})) + 1 + 2 + a + b + c + one + two + three + + > each(print, take(15, cycle(chain(enumerate({"a", "b", "c"}), + {"one", "two", "three"})))) + 1 a + 2 b + 3 c + one + two + three + 1 a + 2 b + 3 c + one + two + three + 1 a + 2 b + 3 c diff --git a/Data/DefaultContent/Libraries/luafun/doc/conf.py b/Data/DefaultContent/Libraries/luafun/doc/conf.py new file mode 100644 index 0000000..ce36bbf --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/conf.py @@ -0,0 +1,247 @@ +# -*- coding: utf-8 -*- +# +# Lua Functional documentation build configuration file, created by +# sphinx-quickstart on Sat Nov 9 14:21:28 2013. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +#extensions = [ "redjack.sphinx.lua" ] + +# The documentation primary domain is lua +#primary_domain = "lua" + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Lua Functional' +copyright = u'2013-2017, Roman Tsisyk' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.1' +# The full version, including alpha/beta/rc tags. +release = '0.1.3' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'haiku' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = { + #"full_logo": False, +#} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +html_logo = "logo.png" + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +#htmlhelp_basename = 'LuaFunctionaldoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +#latex_documents = [ + #('index', 'LuaFunctional.tex', u'Lua Functional Documentation', + #u'Roman Tsisyk', 'manual'), +#] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'luafun', u'Lua Functional Documentation', + [u'Roman Tsisyk'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +#texinfo_documents = [ + #('index', 'LuaFunctional', u'Lua Functional Documentation', + #u'Roman Tsisyk', 'LuaFunctional', 'One line description of project.', + #'Miscellaneous'), +#] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' diff --git a/Data/DefaultContent/Libraries/luafun/doc/filtering.rst b/Data/DefaultContent/Libraries/luafun/doc/filtering.rst new file mode 100644 index 0000000..2852f6c --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/filtering.rst @@ -0,0 +1,121 @@ +Filtering +========= + +.. module:: fun + +This section contains functions to filter values during iteration. + +.. function:: filter(predicate, gen, param, state) + iterator:filter(predicate) + + :param param: an predicate to filter the iterator + :type param: (function(...) -> bool) + + Return a new iterator of those elements that satisfy the **predicate**. + + Examples: + + .. code-block:: lua + + > each(print, filter(function(x) return x % 3 == 0 end, range(10))) + 3 + 6 + 9 + + > each(print, take(5, filter(function(i, x) return i % 3 == 0 end, + enumerate(duplicate('x'))))) + 3 x + 6 x + 9 x + 12 x + 15 x + + .. note:: Multireturn iterators are supported but can cause performance + regressions. + + .. seealso:: :func:`take_while` and :func:`drop_while`. + +.. function:: remove_if(predicate, gen, param, state) + iterator:remove_if(predicate) + + An alias for :func:`filter`. + +.. function:: grep(regexp_or_predicate, gen, param, state) + iterator:grep(regexp_or_predicate) + + If **regexp_or_predicate** is string then the parameter is used as a regular + expression to build filtering predicate. Otherwise the function is just an + alias for :func:`filter`. + + Equivalent to: + + .. code-block:: lua + + local fun = regexp_or_predicate + if type(regexp_or_predicate) == "string" then + fun = function(x) return string.find(x, regexp_or_predicate) ~= nil end + end + return filter(fun, gen, param, state) + + Examples: + + .. code-block:: lua + + lines_to_grep = { + [[Emily]], + [[Chloe]], + [[Megan]], + [[Jessica]], + [[Emma]], + [[Sarah]], + [[Elizabeth]], + [[Sophie]], + [[Olivia]], + [[Lauren]] + } + + each(print, grep("^Em", lines_to_grep)) + --[[test + Emily + Emma + --test]] + + each(print, grep("^P", lines_to_grep)) + --[[test + --test]] + + > each(print, grep(function(x) return x % 3 == 0 end, range(10))) + 3 + 6 + 9 + +.. function:: partition(predicate, gen, param, state) + iterator:partition(predicate) + + :param x: a value to find + :returns: {gen1, param1, state1}, {gen2, param2, state2} + + The function returns two iterators where elements do and do not satisfy the + prediucate. Equivalent to: + + .. code-block:: lua + + return filter(predicate, gen', param', state'), + filter(function(...) return not predicate(...) end, gen, param, state); + + The function make a clone of the source iterator. Iterators especially + returned in tables to work with :func:`zip` and other functions. + + Examples: + + .. code-block:: lua + + > each(print, zip(partition(function(i, x) return i % 3 == 0 end, range(10)))) + 3 1 + 6 2 + 9 4 + + .. note:: ``gen, param, state`` must be pure functional to work properly + with the function. + + .. seealso:: :func:`span` diff --git a/Data/DefaultContent/Libraries/luafun/doc/generators.rst b/Data/DefaultContent/Libraries/luafun/doc/generators.rst new file mode 100644 index 0000000..7132d47 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/generators.rst @@ -0,0 +1,233 @@ +Generators +========== + +.. module:: fun + +This section contains a number of useful generators modeled after Standard ML, +Haskell, Python, Ruby, JavaScript and other languages. + +Finite Generators +----------------- + +.. function:: range([start,] stop[, step]) + + :param start: an endpoint of the interval (see below) + :type start: number + :param stop: an endpoint of the interval (see below) + :type stop: number + :param step: a step + :type step: number + + :returns: an iterator + + The iterator to create arithmetic progressions. Iteration values are generated + within closed interval ``[start, stop]`` (i.e. *stop* is included). + If the *start* argument is omitted, it defaults to ``1`` (*stop* > 0) or + to ``-1`` (*stop* < 0). If the *step* argument is omitted, it defaults to + ``1`` (*start* <= *stop*) or to ``-1`` (*start* > *stop*). If *step* is + positive, the last element is the largest ``start + i * step`` less than or + equal to *stop*; if *step* is negative, the last element is the smallest + ``start + i * step`` greater than or equal to *stop*. + *step* must not be zero (or else an error is raised). + ``range(0)`` returns empty iterator. + + Examples: + + .. code-block:: lua + + > for _it, v in range(5) do print(v) end + 1 + 2 + 3 + 4 + 5 + > for _it, v in range(-5) do print(v) end + -1 + -2 + -3 + -4 + -5 + > for _it, v in range(1, 6) do print(v) end + 1 + 2 + 3 + 4 + 5 + 6 + > for _it, v in range(0, 20, 5) do print(v) end + 0 + 5 + 10 + 15 + 20 + > for _it, v in range(0, 10, 3) do print(v) end + 0 + 3 + 6 + 9 + > for _it, v in range(0, 1.5, 0.2) do print(v) end + 0 + 0.2 + 0.4 + 0.6 + 0.8 + 1 + 1.2 + 1.4 + > for _it, v in range(0) do print(v) end + > for _it, v in range(1) do print(v) end + 1 + > for _it, v in range(1, 0) do print(v) end + 1 + 0 + > for _it, v in range(0, 10, 0) do print(v) end + error: step must not be zero + +Infinity Generators +------------------- + +.. function:: duplicate(...) + + :param ...: objects to duplicate + :type ...: non nil + :returns: an iterator + + The iterator returns values over and over again indefinitely. All values + that passed to the iterator are returned as-is during the iteration. + + Examples: + + .. code-block:: lua + + > each(print, take(3, duplicate('a', 'b', 'c'))) + a b c + a b c + > each(print, take(3, duplicate('x'))) + x + x + x + > for _it, a, b, c, d, e in take(3, duplicate(1, 2, 'a', 3, 'b')) do + print(a, b, c, d, e) + >> end + 1 2 a 3 b + 1 2 a 3 b + 1 2 a 3 b + +.. function:: xrepeat(...) + + An alias for :func:`duplicate`. + +.. function:: replicate(...) + + An alias for :func:`duplicate`. + +.. function:: tabulate(fun) + + :param fun: an unary generating function + :type fun: function(n: uint) -> ... + :returns: an iterator + + The iterator that returns ``fun(0)``, ``fun(1)``, ``fun(2)``, ``...`` values + indefinitely. + + Examples: + + .. code-block:: lua + + > each(print, take(5, tabulate(function(x) return 'a', 'b', 2*x end))) + a b 0 + a b 2 + a b 4 + a b 6 + a b 8 + > each(print, take(5, tabulate(function(x) return x^2 end))) + 0 + 1 + 4 + 9 + 16 + +.. function:: zeros() + + :returns: an iterator + + The iterator returns ``0`` indefinitely. + + Examples: + + .. code-block:: lua + + > each(print, take(5, zeros())) + 0 + 0 + 0 + 0 + 0 + +.. function:: ones() + + :returns: an iterator + + The iterator that returns ``1`` indefinitely. + + Example:: + + > each(print, take(5, ones())) + 1 + 1 + 1 + 1 + 1 + +Random sampling +--------------- + +.. function:: rands([n[, m]]) + + :param n: an endpoint of the interval (see below) + :type n: uint + :param m: an endpoint of the interval (see below) + :type m: uint + :returns: an iterator + + The iterator returns random values using :func:`math.random`. + If the **n** and **m** are set then the iterator returns pseudo-random + integers in the ``[n, m)`` interval (i.e. **m** is not included). + If the **m** is not set then the iterator generates pseudo-random integers + in the ``[0, n)`` interval. When called without arguments returns + pseudo-random real numbers with uniform distribution in the + interval ``[0, 1)``. + + .. warning:: This iterator is not pure-functional and may not work as + expected with some library functions. + + Examples: + + .. code-block:: lua + + > each(print, take(10, rands(10, 20))) + 19 + 17 + 11 + 19 + 12 + 13 + 14 + 16 + 10 + 11 + + > each(print, take(5, rands(10))) + 7 + 6 + 5 + 9 + 0 + + > each(print, take(5, rands())) + 0.79420629243124 + 0.69885246563716 + 0.5901037417281 + 0.7532286166836 + 0.080971251199854 + diff --git a/Data/DefaultContent/Libraries/luafun/doc/getting_started.rst b/Data/DefaultContent/Libraries/luafun/doc/getting_started.rst new file mode 100644 index 0000000..9a9e3de --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/getting_started.rst @@ -0,0 +1,254 @@ +Getting Started +=============== + +Please jump to `Using the Library`_ section if you are familiar with Lua and +LuaJIT. + +.. contents:: + +Prerequisites +------------- + +The library is designed for LuaJIT_. **LuaJIT 2.1 alpha** is high^W **Highly** +recommended for performance reasons. Lua 5.1--5.3 are also supported. + +The library is platform-independent and expected to work on all platforms that +supported by Lua(JIT). It can be also used in any Lua(JIT) based applications, +e.g. Tarantool_ or OpenResty_. + +You might need diff_ tool to run test system and sphinx_ to regenerate the +documentation from source files. + +.. _LuaJIT: http://luajit.org/ +.. _Tarantool: http://tarantool.org/ +.. _OpenResty: http://openresty.org/ +.. _diff: http://en.wikipedia.org/wiki/Diff +.. _sphinx: http://sphinx-doc.org/ + +Installing LuaJIT +----------------- + +You can build LuaJIT from sources or install it from a binary archive. + +From Sources +```````````` + +1. Clone LuaJIT git repository. Please note that **v2.1** branch is needed. +You can always select this branch using ``git checkout v2.1``. + +.. code-block:: bash + + $ git clone http://luajit.org/git/luajit-2.0.git -b v2.1 luajit-2.1 + Cloning into 'luajit-2.1'... + +2. Compile LuaJIT + +.. code-block:: bash + + $ cd luajit-2.1/ + luajit-2.1 $ make -j8 + +3. Install LuaJIT + +.. code-block:: bash + + luajit-2.1 $ make install + luajit-2.1 $ ln -s /usr/local/bin/luajit-2.1.0-alpha /usr/local/bin/luajit + +Install operation might require root permissions. However, you can install +LuaJIT into your home directory. + +From a Binary Archive +````````````````````` + +If operations above look too complicated for you, you always can download a +binary archive from http://luajit.org/download.html page. +Your favorite package manager may also have LuaJIT packages. + +Running LuaJIT +`````````````` + +Ensure that freshly installed LuaJIT works: + +.. code-block:: bash + + $ luajit + LuaJIT 2.1.0-alpha -- Copyright (C) 2005-2013 Mike Pall. http://luajit.org/ + JIT: ON SSE2 SSE3 SSE4.1 fold cse dce fwd dse narrow loop abc sink fuse + > = 2 + 2 + 4 + +It is good idea to use LuaJIT CLI under ``rlwrap`` (on nix platforms): + +.. code-block:: bash + + alias luajit="rlwrap luajit" + $ luajit + LuaJIT 2.1.0-alpha -- Copyright (C) 2005-2013 Mike Pall. http://luajit.org/ + JIT: ON SSE2 SSE3 SSE4.1 fold cse dce fwd dse narrow loop abc sink fuse + > = 2 + 2 + 4 + > = 2 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Data/DefaultContent/Libraries/luafun/doc/make.bat b/Data/DefaultContent/Libraries/luafun/doc/make.bat new file mode 100644 index 0000000..0f68e89 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/make.bat @@ -0,0 +1,190 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\LuaFunctional.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\LuaFunctional.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff --git a/Data/DefaultContent/Libraries/luafun/doc/operators.rst b/Data/DefaultContent/Libraries/luafun/doc/operators.rst new file mode 100644 index 0000000..2f3edd4 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/operators.rst @@ -0,0 +1,203 @@ +Operators +========= + +.. module:: fun.operator + +This auxiliary module exports a set of Lua operators as intrinsic functions +to use with the library high-order primitives. + +.. contents:: + +.. note:: **op** can be used as a shortcut to **operator**. + +Comparison operators +-------------------- + +.. seealso:: `Lua Relational Operators + `_ + +.. function:: le(a, b) + + :returns: **a** <= **b** + +.. function:: lt(a, b) + + :returns: **a** < **b** + +.. function:: eq(a, b) + + :returns: **a** == **b** + +.. function:: ne(a, b) + + :returns: **a** ~= **b** + +.. function:: ge(a, b) + + :returns: **a** >= **b** + +.. function:: gt(a, b) + + :returns: **a** > **b** + +Arithmetic operators +-------------------- + +.. seealso:: `Lua Arithmetic Operators + `_ + +.. function:: add(a, b) + + :returns: **a** + **b** + +.. function:: div(a, b) + + An alias for :func:`truediv`. + +.. function:: truediv(a, b) + + :returns: **a** / **b** + + Performs "true" float division. + Examples: + + .. code-block:: lua + + > print(operator.div(10, 3)) + 3.3333333333333 + > print(operator.div(-10, 3)) + -3.3333333333333 + +.. function:: floordiv(a, b) + + :returns: math.floor(**a** / **b**) + + Performs division where a result is rounded down. Examples: + + .. code-block:: lua + + > print(operator.floordiv(10, 3)) + 3 + > print(operator.floordiv(12, 3)) + 4 + > print(operator.floordiv(-10, 3)) + -4 + > print(operator.floordiv(-12, 3)) + -4 + +.. function:: intdiv(a, b) + + Performs C-like integer division. + + Equvalent to: + + .. code-block:: lua + + function(a, b) + local q = a / b + if a >= 0 then return math.floor(q) else return math.ceil(q) end + end + + Examples: + + .. code-block:: lua + + > print(operator.floordiv(10, 3)) + 3 + > print(operator.floordiv(12, 3)) + 4 + > print(operator.floordiv(-10, 3)) + -3 + > print(operator.floordiv(-12, 3)) + -4 + +.. function:: mod(a, b) + + :returns: **a** % **b** + + .. note:: Result has same sign as **divisor**. Modulo in Lua is defined as + ``a % b == a - math.floor(a/b)*b``. + + Examples: + + .. code-block:: lua + :emphasize-lines: 5-6 + + > print(operator.mod(10, 2)) + 0 + > print(operator.mod(10, 3)) + 2 + print(operator.mod(-10, 3)) + 2 -- == -1 in C, Java, JavaScript and but not in Lua, Python, Haskell! + +.. function:: neq(a) + + :returns: -**a** + +.. function:: unm(a) + + Unary minus. An alias for :func:`neq`. + +.. function:: pow(a, b) + + :returns: math.pow(**a**, **b**) + +.. function:: sub(a, b) + + :returns: **a** - **b** + +String operators +---------------- + +.. seealso:: `Lua Concatenation Operator + `_ + +.. function:: concat(a, b) + + :returns: **a** .. **b** + +.. function:: len(a) + + :returns: # **a** + +.. function:: length(a) + + An alias for :func:`len`. + +Logical operators +----------------- + +.. seealso:: `Lua Logical Operators + `_ + +.. function:: land(a, b) + + :returns: **a** and **b** + +.. function:: lor(a, b) + + :returns: **a** or **b** + +.. function:: lnot(a) + + :returns: not **a** + +.. function:: truth(a) + + :returns: not not **a** + + Return ``true`` if **a** is true, and ``false`` otherwise. Examples: + + .. code-block:: lua + + > print(operator.truth(1)) + true + > print(operator.truth(0)) + true -- It is Lua, baby! + > print(operator.truth(nil)) + false + > print(operator.truth("")) + true + > print(operator.truth({})) + true + diff --git a/Data/DefaultContent/Libraries/luafun/doc/reducing.rst b/Data/DefaultContent/Libraries/luafun/doc/reducing.rst new file mode 100644 index 0000000..f7b89da --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/reducing.rst @@ -0,0 +1,323 @@ +Reducing +======== + +.. module:: fun + +The section contains functions to analyze iteration values and recombine +through use of a given combining operation the results of recursively processing +its constituent parts, building up a return value + +.. contents:: + +.. note:: An attempt to use infinity iterators with the most function from + the module causes an infinite loop. + +Folds +----- + +.. function:: foldl(accfun, initval, gen, param, state) + iterator:reduce(accfun, initval) + + :param accfun: an accumulating function + :type param: (function(prevval, ...) -> val) + :param initval: an initial value that passed to **accfun** on the first + iteration + + The function reduces the iterator from left to right using the binary + operator **accfun** and the initial value **initval**. + Equivalent to:: + + local val = initval + for _k, ... in gen, param, state do + val = accfun(val, ...) + end + return val + + Examples: + + .. code-block:: lua + + > print(foldl(function(acc, x) return acc + x end, 0, range(5))) + 15 + + > print(foldl(operator.add, 0, range(5))) + 15 + + > print(foldl(function(acc, x, y) return acc + x * y; end, 0, + zip(range(1, 5), {4, 3, 2, 1}))) + 20 + +.. function:: reduce(accfun, initval, gen, param, state) + iterator:reduce(accfun, initval) + + An alias to :func:`foldl`. + +.. function:: length(gen, param, state) + iterator:length() + + :returns: a number of elements in ``gen, param, state`` iterator. + + Return a number of elements in ``gen, param, state`` iterator. + This function is equivalent to ``#obj`` for basic array and string iterators. + + Examples: + + .. code-block:: lua + + > print(length({"a", "b", "c", "d", "e"})) + 5 + + > print(length({})) + 0 + + > print(length(range(0))) + 0 + + .. warning:: An attempt to call this function on an infinite iterator will + result an infinite loop. + + .. note:: This function has ``O(n)`` complexity for all iterators except + basic array and string iterators. + +.. function:: totable(gen, param, state) + + :returns: a new table (array) from iterated values. + + The function reduces the iterator from left to right using ``table.insert``. + + Examples: + + .. code-block:: lua + + > local tab = totable("abcdef") + > print(type(tab), #tab) + table 6 + > each(print, tab) + a + b + c + d + e + f + +.. function:: tomap(gen, param, state) + + :returns: a new table (map) from iterated values. + + The function reduces the iterator from left to right using + ``tab[val1] = val2`` expression. + + Examples: + + .. code-block:: lua + + > local tab = tomap(zip(range(1, 7), 'abcdef')) + > print(type(tab), #tab) + table 6 + > each(print, iter(tab)) + a + b + c + d + e + f + +Predicates +---------- + +.. function:: is_prefix_of(iterator1, iterator2) + iterator1:is_prefix_of(iterator2) + + The function takes two iterators and returns ``true`` if the first iterator + is a prefix of the second. + + Examples: + + .. code-block:: lua + + > print(is_prefix_of({"a"}, {"a", "b", "c"})) + true + + > print(is_prefix_of(range(6), range(5))) + false + +.. function:: is_null(gen, param, state) + iterator:is_null() + + :returns: true when `gen, param, state`` iterator is empty or finished. + :returns: false otherwise. + + Example:: + + > print(is_null({"a", "b", "c", "d", "e"})) + false + + > print(is_null({})) + true + + > print(is_null(range(0))) + true + +.. function:: all(predicate, gen, param, state) + iterator:all(predicate) + + :param predicate: a predicate + + Returns true if all return values of iterator satisfy the **predicate**. + + Examples: + + .. code-block:: lua + + > print(all(function(x) return x end, {true, true, true, true})) + true + + > print(all(function(x) return x end, {true, true, true, false})) + false + +.. function:: every(predicate, gen, param, state) + + An alias for :func:`all`. + +.. function:: any(predicate, gen, param, state) + iterator:any(predicate) + + :param predicate: a predicate + + Returns ``true`` if at least one return values of iterator satisfy the + **predicate**. The iteration stops on the first such value. Therefore, + infinity iterators that have at least one satisfying value might work. + + Examples: + + .. code-block:: lua + + > print(any(function(x) return x end, {false, false, false, false})) + false + + > print(any(function(x) return x end, {false, false, false, true})) + true + +.. function:: some(predicate, gen, param, state) + + An alias for :func:`any`. + +Special folds +------------- + +.. function:: sum(gen, param, state) + iterator:sum() + + Sum up all iteration values. An optimized alias for:: + + foldl(operator.add, 0, gen, param, state) + + For an empty iterator ``0`` is returned. + + Examples: + + .. code-block:: lua + + > print(sum(range(5))) + 15 + +.. function:: product(gen, param, state) + iterator:product() + + Multiply all iteration values. An optimized alias for:: + + foldl(operator.mul, 1, gen, param, state) + + For an empty iterator ``1`` is returned. + + Examples: + + .. code-block:: lua + + > print(product(range(1, 5))) + 120 + +.. function:: min(gen, param, state) + iterator:min() + + Return a minimum value from the iterator using :func:`operator.min` or ``<`` + for numbers and other types respectivly. The iterator must be + non-null, otherwise an error is raised. + + Examples: + + .. code-block:: lua + + > print(min(range(1, 10, 1))) + 1 + + > print(min({"f", "d", "c", "d", "e"})) + c + + > print(min({})) + error: min: iterator is empty + +.. function:: minimum(gen, param, state) + + An alias for :func:`min`. + +.. function:: min_by(cmp, gen, param, state) + iterator:min_by(cmp) + + Return a minimum value from the iterator using the **cmp** as a ``<`` + operator. The iterator must be non-null, otherwise an error is raised. + + Examples: + + .. code-block:: lua + + > function min_cmp(a, b) if -a < -b then return a else return b end end + > print(min_by(min_cmp, range(1, 10, 1))) + 9 + +.. function:: minimum_by(cmp, gen, param, state) + + An alias for :func:`min_by`. + +.. function:: max(gen, param, state) + iterator:max() + + Return a maximum value from the iterator using :func:`operator.max` or ``>`` + for numbers and other types respectivly. + + The iterator must be non-null, otherwise an error is raised. + + Examples: + + .. code-block:: lua + + > print(max(range(1, 10, 1))) + 9 + + > print(max({"f", "d", "c", "d", "e"})) + f + + > print(max({})) + error: max: iterator is empty + +.. function:: maximum(gen, param, state) + + An alias for :func:`max`. + +.. function:: max_by(cmp, gen, param, state) + iterator:max_by(cmp) + + Return a maximum value from the iterator using the **cmp** as a `>` + operator. The iterator must be non-null, otherwise an error is raised. + + Examples: + + .. code-block:: lua + + > function max_cmp(a, b) if -a > -b then return a else return b end end + > print(max_by(max_cmp, range(1, 10, 1))) + 1 + +.. function:: maximum_by(cmp, gen, param, state) + + An alias for :func:`max_by`. diff --git a/Data/DefaultContent/Libraries/luafun/doc/reference.rst b/Data/DefaultContent/Libraries/luafun/doc/reference.rst new file mode 100644 index 0000000..f1f9cfc --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/reference.rst @@ -0,0 +1,14 @@ +API Reference +============= + +.. toctree:: + + basic.rst + generators.rst + slicing.rst + indexing.rst + filtering.rst + reducing.rst + transformations.rst + compositions.rst + operators.rst \ No newline at end of file diff --git a/Data/DefaultContent/Libraries/luafun/doc/slicing.rst b/Data/DefaultContent/Libraries/luafun/doc/slicing.rst new file mode 100644 index 0000000..1af642f --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/slicing.rst @@ -0,0 +1,246 @@ +Slicing +======= + +.. module:: fun + +This section contains functions to make subsequences from iterators. + +Basic +----- + +.. function:: nth(n, gen, param, state) + iterator:nth(n) + + :param uint n: a sequential number (indexed starting from ``1``, + like Lua tables) + :returns: **n**-th element of ``gen, param, state`` iterator + + This function returns the **n**-th element of ``gen, param, state`` + iterator. If the iterator does not have **n** items then ``nil`` is returned. + + Examples: + + .. code-block:: lua + + > print(nth(2, range(5))) + 2 + + > print(nth(10, range(5))) + nil + + > print(nth(2, {"a", "b", "c", "d", "e"})) + b + + > print(nth(2, enumerate({"a", "b", "c", "d", "e"}))) + 2 b + + This function is optimized for basic array and string iterators and has + ``O(1)`` complexity for these cases. + +.. function:: head(gen, param, state) + iterator:head() + + :returns: a first element of ``gen, param, state`` iterator + + Extract the first element of ``gen, param, state`` iterator. + If the iterator is empty then an error is raised. + + Examples: + + .. code-block:: lua + + > print(head({"a", "b", "c", "d", "e"})) + a + > print(head({})) + error: head: iterator is empty + > print(head(range(0))) + error: head: iterator is empty + > print(head(enumerate({"a", "b"}))) + 1 a + +.. function:: car(gen, param, state) + + An alias for :func:`head`. + +.. function:: tail(gen, param, state) + iterator:tail() + + :returns: ``gen, param, state`` iterator without a first element + + Return a copy of ``gen, param, state`` iterator without its first element. + If the iterator is empty then an empty iterator is returned. + + Examples: + + .. code-block:: lua + + > each(print, tail({"a", "b", "c", "d", "e"})) + b + c + d + e + > each(print, tail({})) + > each(print, tail(range(0))) + > each(print, tail(enumerate({"a", "b", "c"}))) + 2 b + 3 c + +.. function:: cdr(gen, param, state) + + An alias for :func:`tail`. + +Subsequences +------------ + +.. function:: take_n(n, gen, param, state) + iterator:take_n(n) + + :param n: a number of elements to take + :type n: uint + :returns: an iterator on the subsequence of first **n** elements + + Examples: + + .. code-block:: lua + + > each(print, take_n(5, range(10))) + 1 + 2 + 3 + 4 + 5 + + > each(print, take_n(5, enumerate(duplicate('x')))) + 1 x + 2 x + 3 x + 4 x + 5 x + +.. function:: take_while(predicate, gen, param, state) + iterator:take_while(predicate) + + :type predicate: function(...) -> bool + :returns: an iterator on the longest prefix of ``gen, param, state`` + elements that satisfy **predicate**. + + Examples: + + .. code-block:: lua + + > each(print, take_while(function(x) return x < 5 end, range(10))) + 1 + 2 + 3 + 4 + + > each(print, take_while(function(i, a) return i ~=a end, + enumerate({5, 3, 4, 4, 2}))) + 1 5 + 2 3 + 3 4 + + .. seealso:: :func:`filter` + +.. function:: take(n_or_predicate, gen, param, state) + iterator:take(n_or_predicate) + + An alias for :func:`take_n` and :func:`take_while` that autodetects + required function based on **n_or_predicate** type. + +.. function:: drop_n(n, gen, param, state) + iterator:drop_n(n) + + :param n: the number of elements to drop + :type n: uint + :returns: ``gen, param, state`` iterator after skipping first **n** + elements + + Examples: + + .. code-block:: lua + + > each(print, drop_n(2, range(5))) + 3 + 4 + 5 + + > each(print, drop_n(2, enumerate({'a', 'b', 'c', 'd', 'e'}))) + 3 c + 4 d + 5 e + +.. function:: drop_while(predicate, gen, param, state) + iterator:drop_while(predicate) + + :type predicate: function(...) -> bool + :returns: ``gen, param, state`` after skipping the longest prefix + of elements that satisfy **predicate**. + + Examples: + + .. code-block:: lua + + > each(print, drop_while(function(x) return x < 5 end, range(10))) + 5 + 6 + 7 + 8 + 9 + 10 + + .. seealso:: :func:`filter` + +.. function:: drop(n_or_predicate, gen, param, state) + iterator:drop(n_or_predicate) + + An alias for :func:`drop_n` and :func:`drop_while` that autodetects + required function based on **n_or_predicate** type. + + +.. function:: span(n_or_predicate, gen, param, state) + iterator:span(n_or_predicate) + + :type n_or_predicate: function(...) -> bool or uint + :returns: iterator, iterator + + Return an iterator pair where the first operates on the longest prefix + (possibly empty) of ``gen, param, state`` iterator of elements that + satisfy **predicate** and second operates the remainder of + ``gen, param, state`` iterator. + Equivalent to: + + .. code-block:: lua + + return take(n_or_predicate, gen, param, state), + drop(n_or_predicate, gen, param, state); + + Examples: + + .. code-block:: lua + + > each(print, zip(span(function(x) return x < 5 end, range(10)))) + 1 5 + 2 6 + 3 7 + 4 8 + + > each(print, zip(span(5, range(10)))) + 1 6 + 2 7 + 3 8 + 4 9 + 5 10 + + .. note:: ``gen, param, state`` must be pure functional to work properly + with the function. + + .. seealso:: :func:`partition` + +.. function:: split(n_or_predicate, gen, param, state) + + An alias for :func:`span`. + +.. function:: split_at(n, gen, param, state) + + An alias for :func:`span`. diff --git a/Data/DefaultContent/Libraries/luafun/doc/transformations.rst b/Data/DefaultContent/Libraries/luafun/doc/transformations.rst new file mode 100644 index 0000000..e446d2f --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/transformations.rst @@ -0,0 +1,87 @@ +Transformations +=============== + +.. module:: fun + +.. function:: map(fun, gen, param, state) + iterator:map(fun) + + :param fun: a function to apply + :type fun: (function(...) -> ...) + :returns: a new iterator + + Return a new iterator by applying the **fun** to each element of + ``gen, param, state`` iterator. The mapping is performed on the fly + and no values are buffered. + + Examples: + + .. code-block:: lua + + > each(print, map(function(x) return 2 * x end, range(4))) + 2 + 4 + 6 + 8 + + fun = function(...) return 'map', ... end + > each(print, map(fun, range(4))) + map 1 + map 2 + map 3 + map 4 + +.. function:: enumerate(gen, param, state) + iterator:enumerate() + + :returns: a new iterator + + Return a new iterator by enumerating all elements of the + ``gen, param, state`` iterator starting from ``1``. The mapping is performed + on the fly and no values are buffered. + + Examples: + + .. code-block:: lua + + > each(print, enumerate({"a", "b", "c", "d", "e"})) + 1 a + 2 b + 3 c + 4 d + 5 e + + > each(print, enumerate(zip({"one", "two", "three", "four", "five"}, + {"a", "b", "c", "d", "e"}))) + 1 one a + 2 two b + 3 three c + 4 four d + 5 five e + +.. function:: intersperse(x, gen, param, state) + iterator:intersperse(x) + + :type x: any + :returns: a new iterator + + Return a new iterator where the **x** value is interspersed between the + elements of the source iterator. The **x** value can also be added as a + last element of returning iterator if the source iterator contains the odd + number of elements. + + Examples: + + .. code-block:: lua + + > each(print, intersperse("x", {"a", "b", "c", "d", "e"})) + a + x + b + x + c + x + d + x + e + x diff --git a/Data/DefaultContent/Libraries/luafun/doc/under_the_hood.rst b/Data/DefaultContent/Libraries/luafun/doc/under_the_hood.rst new file mode 100644 index 0000000..802659e --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/doc/under_the_hood.rst @@ -0,0 +1,154 @@ +Under the Hood +============== + +.. module:: fun + +The section shed some light on the internal library structure and working +principles. + +Iterators +--------- + +A basic primitive of the library after functions is an iterator. Most functions +takes an iterator and returns a new iteraror(s). Iterators all the way down! +[#iterators]_. + +The simplest iterator is (surprise!) :func:`pairs` and :func:`ipairs` +Lua functions. Have you ever tried to call, say, :func:`ipairs` function +without using it inside a ``for`` loop? Try to do that on any Lua +implementation: + +.. _iterator_triplet: +.. code-block:: bash + + > =ipairs({'a', 'b', 'c'}) + function: builtin#6 table: 0x40f80e38 0 + +The function returned three strange values which look useless without a ``for`` +loop. We call these values **iterator triplet**. +Let's see how each value is used for: + +``gen`` -- first value + A generating function that can produce a next value on each iteration. + Usually returns a new ``state`` and iteration values (multireturn). + +``param`` -- second value + A permanent (constant) parameter of a generating function is used to create + specific instance of the generating function. For example, a table itself + for ``ipairs`` case. + +``state`` -- third value + A some transient state of an iterator that is changed after each iteration. + For example, an array index for ``ipairs`` case. + +Try to call ``gen`` function manually: + + .. code-block:: lua + + > gen, param, state = ipairs({'a', 'b', 'c'}) + > =gen(param, state) + 1 a + +The ``gen`` function returned a new state ``1`` and the next iteration +value ``a``. The second call to ``gen`` with the new state will return the next +state and the next iteration value. When the iterator finishes to the end +the ``nil`` value is returned instead of the next state. + +**Please do not panic!** You do not have to use these values directly. +It is just a nice trick to get ``for .. in`` loop working in Lua. + +Iterations +---------- + +What happens when you type the following code into a Lua console:: + + for _it, x in ipairs({'a', 'b', 'c'}) do print(x) end + +According to Lua reference manual [#lua_for]_ the code above is equivalent to:: + + do + -- Initialize the iterator + local gen, param, state = ipairs({'a', 'b', 'c'}) + while true do + -- Next iteration + local state, var_1, ···, var_n = gen(param, state) + if state == nil then break end + -- Assign values to our variables + _it = state + x = var_1 + -- Execute the code block + print(x) + end + end + +What does it mean for us? + +* An iterator can be used together with ``for .. in`` to generate a loop +* An iterator is fully defined using ``gen``, ``param`` and ``state`` iterator + triplet +* The ``nil`` state marks the end of an iteration +* An iterator can return an arbitrary number of values (multireturn) +* It is possible to make some wrapping functions to take an iterator and + + return a new modified iterator + +**The library provides a set of iterators** that can be used like ``pairs`` +and ``ipairs``. + +Iterator Types +-------------- + +Pure functional iterators +````````````````````````` + +Iterators can be either pure functional or have some side effects and returns +different values for some initial conditions [#pure_function]_. An **iterator is +pure functional** if it meets the following criteria: + +- ``gen`` function always returns the same values for the same ``param`` and + ``state`` values (idempotence property) +- ``param`` and ``state`` values are not modified during ``gen`` call and + a new ``state`` object is returned instead (referential transparency + property). + +Pure functional iterators are very important for us. Pure functional iterator +can be safety cloned or reapplied without creating side effects. Many library +function use these properties. + +Finite iterators +```````````````` + +Iterators can be **finite** (sooner or later end up) or **infinite** +(never end). +Since there is no way to determine automatically if an iterator is finite or +not [#turing]_ the library function can not automatically resolve infinite +loops. It is your obligation to do not pass infinite iterator to reducing +functions. + +Tracing JIT +----------- + +Tracing just-in-time compilation is a technique used by virtual machines to +optimize the execution of a program at runtime. This is done by recording a +linear sequence of frequently executed operations, compiling them to native +machine code and executing them. + +First profiling information for loops is collected. After a hot loop has been +identified, a special tracing mode is entered which records all executed +operations of that loop. This sequence of operations is called a **trace**. +The trace is then optimized and compiled to machine code (trace). When this +loop is executed again the compiled trace is called instead of the program +counterpart [#tracing_jit]_. + +Why the tracing JIT is important for us? The LuaJIT tracing compiler can detect +tail-, up- and down-recursion [#luajit-recursion]_, unroll compositions of +functions and inline high-order functions [#luajit-optimizations]_. +All of these concepts make the foundation for functional programming. + +.. [#iterators] http://en.wikipedia.org/wiki/Turtles_all_the_way_down +.. [#lua_for] http://www.lua.org/manual/5.2/manual.html#3.3.5 +.. [#pure_function] http://en.wikipedia.org/wiki/Pure_function +.. [#turing] `Proved by Turing `_ +.. [#tracing_jit] http://en.wikipedia.org/wiki/Tracing_just-in-time_compilation +.. [#luajit-recursion] http://lambda-the-ultimate.org/node/3851#comment-57679 +.. [#luajit-optimizations] http://wiki.luajit.org/Optimizations diff --git a/Data/DefaultContent/Libraries/luafun/fun-scm-1.rockspec b/Data/DefaultContent/Libraries/luafun/fun-scm-1.rockspec new file mode 100644 index 0000000..8f22022 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/fun-scm-1.rockspec @@ -0,0 +1,34 @@ +package = "fun" +version = "scm-1" + +source = { + url = "git://github.com/luafun/luafun.git", +} + +description = { + summary = "High-performance functional programming library for Lua", + homepage = "https://luafun.github.io/", + license = "MIT/X11", + maintainer = "Roman Tsisyk ", + detailed = [[ +Lua Fun is a high-performance functional programming library for Lua +designed with LuaJIT's trace compiler in mind. + +Lua Fun provides a set of more than 50 programming primitives typically +found in languages like Standard ML, Haskell, Erlang, JavaScript, Python and +even Lisp. High-order functions such as map, filter, reduce, zip, etc., +make it easy to write simple and efficient functional code. +]] +} + +dependencies = { + "lua" +} + +build = { + type = "builtin", + modules = { + fun = "fun.lua", + }, + copy_directories = { "tests" }, +} diff --git a/Data/DefaultContent/Libraries/luafun/fun.lua b/Data/DefaultContent/Libraries/luafun/fun.lua new file mode 100644 index 0000000..2427bb2 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/fun.lua @@ -0,0 +1,1058 @@ +--- +--- Lua Fun - a high-performance functional programming library for LuaJIT +--- +--- Copyright (c) 2013-2017 Roman Tsisyk +--- +--- Distributed under the MIT/X11 License. See COPYING.md for more details. +--- + +local exports = {} +local methods = {} + +-- compatibility with Lua 5.1/5.2 +local unpack = rawget(table, "unpack") or unpack + +-------------------------------------------------------------------------------- +-- Tools +-------------------------------------------------------------------------------- + +local return_if_not_empty = function(state_x, ...) + if state_x == nil then + return nil + end + return ... +end + +local call_if_not_empty = function(fun, state_x, ...) + if state_x == nil then + return nil + end + return state_x, fun(...) +end + +local function deepcopy(orig) -- used by cycle() + local orig_type = type(orig) + local copy + if orig_type == 'table' then + copy = {} + for orig_key, orig_value in next, orig, nil do + copy[deepcopy(orig_key)] = deepcopy(orig_value) + end + else + copy = orig + end + return copy +end + +local iterator_mt = { + -- usually called by for-in loop + __call = function(self, param, state) + return self.gen(param, state) + end; + __tostring = function(self) + return '' + end; + -- add all exported methods + __index = methods; +} + +local wrap = function(gen, param, state) + return setmetatable({ + gen = gen, + param = param, + state = state + }, iterator_mt), param, state +end +exports.wrap = wrap + +local unwrap = function(self) + return self.gen, self.param, self.state +end +methods.unwrap = unwrap + +-------------------------------------------------------------------------------- +-- Basic Functions +-------------------------------------------------------------------------------- + +local nil_gen = function(_param, _state) + return nil +end + +local string_gen = function(param, state) + local state = state + 1 + if state > #param then + return nil + end + local r = string.sub(param, state, state) + return state, r +end + +local ipairs_gen = ipairs({}) -- get the generating function from ipairs + +local pairs_gen = pairs({ a = 0 }) -- get the generating function from pairs +local map_gen = function(tab, key) + local value + local key, value = pairs_gen(tab, key) + return key, key, value +end + +local rawiter = function(obj, param, state) + assert(obj ~= nil, "invalid iterator") + if type(obj) == "table" then + local mt = getmetatable(obj); + if mt ~= nil then + if mt == iterator_mt then + return obj.gen, obj.param, obj.state + elseif mt.__ipairs ~= nil then + return mt.__ipairs(obj) + elseif mt.__pairs ~= nil then + return mt.__pairs(obj) + end + end + if #obj > 0 then + -- array + return ipairs(obj) + else + -- hash + return map_gen, obj, nil + end + elseif (type(obj) == "function") then + return obj, param, state + elseif (type(obj) == "string") then + if #obj == 0 then + return nil_gen, nil, nil + end + return string_gen, obj, 0 + end + error(string.format('object %s of type "%s" is not iterable', + obj, type(obj))) +end + +local iter = function(obj, param, state) + return wrap(rawiter(obj, param, state)) +end +exports.iter = iter + +local method0 = function(fun) + return function(self) + return fun(self.gen, self.param, self.state) + end +end + +local method1 = function(fun) + return function(self, arg1) + return fun(arg1, self.gen, self.param, self.state) + end +end + +local method2 = function(fun) + return function(self, arg1, arg2) + return fun(arg1, arg2, self.gen, self.param, self.state) + end +end + +local export0 = function(fun) + return function(gen, param, state) + return fun(rawiter(gen, param, state)) + end +end + +local export1 = function(fun) + return function(arg1, gen, param, state) + return fun(arg1, rawiter(gen, param, state)) + end +end + +local export2 = function(fun) + return function(arg1, arg2, gen, param, state) + return fun(arg1, arg2, rawiter(gen, param, state)) + end +end + +local each = function(fun, gen, param, state) + repeat + state = call_if_not_empty(fun, gen(param, state)) + until state == nil +end +methods.each = method1(each) +exports.each = export1(each) +methods.for_each = methods.each +exports.for_each = exports.each +methods.foreach = methods.each +exports.foreach = exports.each + +-------------------------------------------------------------------------------- +-- Generators +-------------------------------------------------------------------------------- + +local range_gen = function(param, state) + local stop, step = param[1], param[2] + local state = state + step + if state > stop then + return nil + end + return state, state +end + +local range_rev_gen = function(param, state) + local stop, step = param[1], param[2] + local state = state + step + if state < stop then + return nil + end + return state, state +end + +local range = function(start, stop, step) + if step == nil then + if stop == nil then + if start == 0 then + return nil_gen, nil, nil + end + stop = start + start = stop > 0 and 1 or -1 + end + step = start <= stop and 1 or -1 + end + + assert(type(start) == "number", "start must be a number") + assert(type(stop) == "number", "stop must be a number") + assert(type(step) == "number", "step must be a number") + assert(step ~= 0, "step must not be zero") + + if (step > 0) then + return wrap(range_gen, {stop, step}, start - step) + elseif (step < 0) then + return wrap(range_rev_gen, {stop, step}, start - step) + end +end +exports.range = range + +local duplicate_table_gen = function(param_x, state_x) + return state_x + 1, unpack(param_x) +end + +local duplicate_fun_gen = function(param_x, state_x) + return state_x + 1, param_x(state_x) +end + +local duplicate_gen = function(param_x, state_x) + return state_x + 1, param_x +end + +local duplicate = function(...) + if select('#', ...) <= 1 then + return wrap(duplicate_gen, select(1, ...), 0) + else + return wrap(duplicate_table_gen, {...}, 0) + end +end +exports.duplicate = duplicate +exports.replicate = duplicate +exports.xrepeat = duplicate + +local tabulate = function(fun) + assert(type(fun) == "function") + return wrap(duplicate_fun_gen, fun, 0) +end +exports.tabulate = tabulate + +local zeros = function() + return wrap(duplicate_gen, 0, 0) +end +exports.zeros = zeros + +local ones = function() + return wrap(duplicate_gen, 1, 0) +end +exports.ones = ones + +local rands_gen = function(param_x, _state_x) + return 0, math.random(param_x[1], param_x[2]) +end + +local rands_nil_gen = function(_param_x, _state_x) + return 0, math.random() +end + +local rands = function(n, m) + if n == nil and m == nil then + return wrap(rands_nil_gen, 0, 0) + end + assert(type(n) == "number", "invalid first arg to rands") + if m == nil then + m = n + n = 0 + else + assert(type(m) == "number", "invalid second arg to rands") + end + assert(n < m, "empty interval") + return wrap(rands_gen, {n, m - 1}, 0) +end +exports.rands = rands + +-------------------------------------------------------------------------------- +-- Slicing +-------------------------------------------------------------------------------- + +local nth = function(n, gen_x, param_x, state_x) + assert(n > 0, "invalid first argument to nth") + -- An optimization for arrays and strings + if gen_x == ipairs_gen then + return param_x[n] + elseif gen_x == string_gen then + if n <= #param_x then + return string.sub(param_x, n, n) + else + return nil + end + end + for i=1,n-1,1 do + state_x = gen_x(param_x, state_x) + if state_x == nil then + return nil + end + end + return return_if_not_empty(gen_x(param_x, state_x)) +end +methods.nth = method1(nth) +exports.nth = export1(nth) + +local head_call = function(state, ...) + if state == nil then + error("head: iterator is empty") + end + return ... +end + +local head = function(gen, param, state) + return head_call(gen(param, state)) +end +methods.head = method0(head) +exports.head = export0(head) +exports.car = exports.head +methods.car = methods.head + +local tail = function(gen, param, state) + state = gen(param, state) + if state == nil then + return wrap(nil_gen, nil, nil) + end + return wrap(gen, param, state) +end +methods.tail = method0(tail) +exports.tail = export0(tail) +exports.cdr = exports.tail +methods.cdr = methods.tail + +local take_n_gen_x = function(i, state_x, ...) + if state_x == nil then + return nil + end + return {i, state_x}, ... +end + +local take_n_gen = function(param, state) + local n, gen_x, param_x = param[1], param[2], param[3] + local i, state_x = state[1], state[2] + if i >= n then + return nil + end + return take_n_gen_x(i + 1, gen_x(param_x, state_x)) +end + +local take_n = function(n, gen, param, state) + assert(n >= 0, "invalid first argument to take_n") + return wrap(take_n_gen, {n, gen, param}, {0, state}) +end +methods.take_n = method1(take_n) +exports.take_n = export1(take_n) + +local take_while_gen_x = function(fun, state_x, ...) + if state_x == nil or not fun(...) then + return nil + end + return state_x, ... +end + +local take_while_gen = function(param, state_x) + local fun, gen_x, param_x = param[1], param[2], param[3] + return take_while_gen_x(fun, gen_x(param_x, state_x)) +end + +local take_while = function(fun, gen, param, state) + assert(type(fun) == "function", "invalid first argument to take_while") + return wrap(take_while_gen, {fun, gen, param}, state) +end +methods.take_while = method1(take_while) +exports.take_while = export1(take_while) + +local take = function(n_or_fun, gen, param, state) + if type(n_or_fun) == "number" then + return take_n(n_or_fun, gen, param, state) + else + return take_while(n_or_fun, gen, param, state) + end +end +methods.take = method1(take) +exports.take = export1(take) + +local drop_n = function(n, gen, param, state) + assert(n >= 0, "invalid first argument to drop_n") + local i + for i=1,n,1 do + state = gen(param, state) + if state == nil then + return wrap(nil_gen, nil, nil) + end + end + return wrap(gen, param, state) +end +methods.drop_n = method1(drop_n) +exports.drop_n = export1(drop_n) + +local drop_while_x = function(fun, state_x, ...) + if state_x == nil or not fun(...) then + return state_x, false + end + return state_x, true, ... +end + +local drop_while = function(fun, gen_x, param_x, state_x) + assert(type(fun) == "function", "invalid first argument to drop_while") + local cont, state_x_prev + repeat + state_x_prev = deepcopy(state_x) + state_x, cont = drop_while_x(fun, gen_x(param_x, state_x)) + until not cont + if state_x == nil then + return wrap(nil_gen, nil, nil) + end + return wrap(gen_x, param_x, state_x_prev) +end +methods.drop_while = method1(drop_while) +exports.drop_while = export1(drop_while) + +local drop = function(n_or_fun, gen_x, param_x, state_x) + if type(n_or_fun) == "number" then + return drop_n(n_or_fun, gen_x, param_x, state_x) + else + return drop_while(n_or_fun, gen_x, param_x, state_x) + end +end +methods.drop = method1(drop) +exports.drop = export1(drop) + +local split = function(n_or_fun, gen_x, param_x, state_x) + return take(n_or_fun, gen_x, param_x, state_x), + drop(n_or_fun, gen_x, param_x, state_x) +end +methods.split = method1(split) +exports.split = export1(split) +methods.split_at = methods.split +exports.split_at = exports.split +methods.span = methods.split +exports.span = exports.split + +-------------------------------------------------------------------------------- +-- Indexing +-------------------------------------------------------------------------------- + +local index = function(x, gen, param, state) + local i = 1 + for _k, r in gen, param, state do + if r == x then + return i + end + i = i + 1 + end + return nil +end +methods.index = method1(index) +exports.index = export1(index) +methods.index_of = methods.index +exports.index_of = exports.index +methods.elem_index = methods.index +exports.elem_index = exports.index + +local indexes_gen = function(param, state) + local x, gen_x, param_x = param[1], param[2], param[3] + local i, state_x = state[1], state[2] + local r + while true do + state_x, r = gen_x(param_x, state_x) + if state_x == nil then + return nil + end + i = i + 1 + if r == x then + return {i, state_x}, i + end + end +end + +local indexes = function(x, gen, param, state) + return wrap(indexes_gen, {x, gen, param}, {0, state}) +end +methods.indexes = method1(indexes) +exports.indexes = export1(indexes) +methods.elem_indexes = methods.indexes +exports.elem_indexes = exports.indexes +methods.indices = methods.indexes +exports.indices = exports.indexes +methods.elem_indices = methods.indexes +exports.elem_indices = exports.indexes + +-------------------------------------------------------------------------------- +-- Filtering +-------------------------------------------------------------------------------- + +local filter1_gen = function(fun, gen_x, param_x, state_x, a) + while true do + if state_x == nil or fun(a) then break; end + state_x, a = gen_x(param_x, state_x) + end + return state_x, a +end + +-- call each other +local filterm_gen +local filterm_gen_shrink = function(fun, gen_x, param_x, state_x) + return filterm_gen(fun, gen_x, param_x, gen_x(param_x, state_x)) +end + +filterm_gen = function(fun, gen_x, param_x, state_x, ...) + if state_x == nil then + return nil + end + if fun(...) then + return state_x, ... + end + return filterm_gen_shrink(fun, gen_x, param_x, state_x) +end + +local filter_detect = function(fun, gen_x, param_x, state_x, ...) + if select('#', ...) < 2 then + return filter1_gen(fun, gen_x, param_x, state_x, ...) + else + return filterm_gen(fun, gen_x, param_x, state_x, ...) + end +end + +local filter_gen = function(param, state_x) + local fun, gen_x, param_x = param[1], param[2], param[3] + return filter_detect(fun, gen_x, param_x, gen_x(param_x, state_x)) +end + +local filter = function(fun, gen, param, state) + return wrap(filter_gen, {fun, gen, param}, state) +end +methods.filter = method1(filter) +exports.filter = export1(filter) +methods.remove_if = methods.filter +exports.remove_if = exports.filter + +local grep = function(fun_or_regexp, gen, param, state) + local fun = fun_or_regexp + if type(fun_or_regexp) == "string" then + fun = function(x) return string.find(x, fun_or_regexp) ~= nil end + end + return filter(fun, gen, param, state) +end +methods.grep = method1(grep) +exports.grep = export1(grep) + +local partition = function(fun, gen, param, state) + local neg_fun = function(...) + return not fun(...) + end + return filter(fun, gen, param, state), + filter(neg_fun, gen, param, state) +end +methods.partition = method1(partition) +exports.partition = export1(partition) + +-------------------------------------------------------------------------------- +-- Reducing +-------------------------------------------------------------------------------- + +local foldl_call = function(fun, start, state, ...) + if state == nil then + return nil, start + end + return state, fun(start, ...) +end + +local foldl = function(fun, start, gen_x, param_x, state_x) + while true do + state_x, start = foldl_call(fun, start, gen_x(param_x, state_x)) + if state_x == nil then + break; + end + end + return start +end +methods.foldl = method2(foldl) +exports.foldl = export2(foldl) +methods.reduce = methods.foldl +exports.reduce = exports.foldl + +local length = function(gen, param, state) + if gen == ipairs_gen or gen == string_gen then + return #param + end + local len = 0 + repeat + state = gen(param, state) + len = len + 1 + until state == nil + return len - 1 +end +methods.length = method0(length) +exports.length = export0(length) + +local is_null = function(gen, param, state) + return gen(param, deepcopy(state)) == nil +end +methods.is_null = method0(is_null) +exports.is_null = export0(is_null) + +local is_prefix_of = function(iter_x, iter_y) + local gen_x, param_x, state_x = iter(iter_x) + local gen_y, param_y, state_y = iter(iter_y) + + local r_x, r_y + for i=1,10,1 do + state_x, r_x = gen_x(param_x, state_x) + state_y, r_y = gen_y(param_y, state_y) + if state_x == nil then + return true + end + if state_y == nil or r_x ~= r_y then + return false + end + end +end +methods.is_prefix_of = is_prefix_of +exports.is_prefix_of = is_prefix_of + +local all = function(fun, gen_x, param_x, state_x) + local r + repeat + state_x, r = call_if_not_empty(fun, gen_x(param_x, state_x)) + until state_x == nil or not r + return state_x == nil +end +methods.all = method1(all) +exports.all = export1(all) +methods.every = methods.all +exports.every = exports.all + +local any = function(fun, gen_x, param_x, state_x) + local r + repeat + state_x, r = call_if_not_empty(fun, gen_x(param_x, state_x)) + until state_x == nil or r + return not not r +end +methods.any = method1(any) +exports.any = export1(any) +methods.some = methods.any +exports.some = exports.any + +local sum = function(gen, param, state) + local s = 0 + local r = 0 + repeat + s = s + r + state, r = gen(param, state) + until state == nil + return s +end +methods.sum = method0(sum) +exports.sum = export0(sum) + +local product = function(gen, param, state) + local p = 1 + local r = 1 + repeat + p = p * r + state, r = gen(param, state) + until state == nil + return p +end +methods.product = method0(product) +exports.product = export0(product) + +local min_cmp = function(m, n) + if n < m then return n else return m end +end + +local max_cmp = function(m, n) + if n > m then return n else return m end +end + +local min = function(gen, param, state) + local state, m = gen(param, state) + if state == nil then + error("min: iterator is empty") + end + + local cmp + if type(m) == "number" then + -- An optimization: use math.min for numbers + cmp = math.min + else + cmp = min_cmp + end + + for _, r in gen, param, state do + m = cmp(m, r) + end + return m +end +methods.min = method0(min) +exports.min = export0(min) +methods.minimum = methods.min +exports.minimum = exports.min + +local min_by = function(cmp, gen_x, param_x, state_x) + local state_x, m = gen_x(param_x, state_x) + if state_x == nil then + error("min: iterator is empty") + end + + for _, r in gen_x, param_x, state_x do + m = cmp(m, r) + end + return m +end +methods.min_by = method1(min_by) +exports.min_by = export1(min_by) +methods.minimum_by = methods.min_by +exports.minimum_by = exports.min_by + +local max = function(gen_x, param_x, state_x) + local state_x, m = gen_x(param_x, state_x) + if state_x == nil then + error("max: iterator is empty") + end + + local cmp + if type(m) == "number" then + -- An optimization: use math.max for numbers + cmp = math.max + else + cmp = max_cmp + end + + for _, r in gen_x, param_x, state_x do + m = cmp(m, r) + end + return m +end +methods.max = method0(max) +exports.max = export0(max) +methods.maximum = methods.max +exports.maximum = exports.max + +local max_by = function(cmp, gen_x, param_x, state_x) + local state_x, m = gen_x(param_x, state_x) + if state_x == nil then + error("max: iterator is empty") + end + + for _, r in gen_x, param_x, state_x do + m = cmp(m, r) + end + return m +end +methods.max_by = method1(max_by) +exports.max_by = export1(max_by) +methods.maximum_by = methods.maximum_by +exports.maximum_by = exports.maximum_by + +local totable = function(gen_x, param_x, state_x) + local tab, key, val = {} + while true do + state_x, val = gen_x(param_x, state_x) + if state_x == nil then + break + end + table.insert(tab, val) + end + return tab +end +methods.totable = method0(totable) +exports.totable = export0(totable) + +local tomap = function(gen_x, param_x, state_x) + local tab, key, val = {} + while true do + state_x, key, val = gen_x(param_x, state_x) + if state_x == nil then + break + end + tab[key] = val + end + return tab +end +methods.tomap = method0(tomap) +exports.tomap = export0(tomap) + +-------------------------------------------------------------------------------- +-- Transformations +-------------------------------------------------------------------------------- + +local map_gen = function(param, state) + local gen_x, param_x, fun = param[1], param[2], param[3] + return call_if_not_empty(fun, gen_x(param_x, state)) +end + +local map = function(fun, gen, param, state) + return wrap(map_gen, {gen, param, fun}, state) +end +methods.map = method1(map) +exports.map = export1(map) + +local enumerate_gen_call = function(state, i, state_x, ...) + if state_x == nil then + return nil + end + return {i + 1, state_x}, i, ... +end + +local enumerate_gen = function(param, state) + local gen_x, param_x = param[1], param[2] + local i, state_x = state[1], state[2] + return enumerate_gen_call(state, i, gen_x(param_x, state_x)) +end + +local enumerate = function(gen, param, state) + return wrap(enumerate_gen, {gen, param}, {1, state}) +end +methods.enumerate = method0(enumerate) +exports.enumerate = export0(enumerate) + +local intersperse_call = function(i, state_x, ...) + if state_x == nil then + return nil + end + return {i + 1, state_x}, ... +end + +local intersperse_gen = function(param, state) + local x, gen_x, param_x = param[1], param[2], param[3] + local i, state_x = state[1], state[2] + if i % 2 == 1 then + return {i + 1, state_x}, x + else + return intersperse_call(i, gen_x(param_x, state_x)) + end +end + +-- TODO: interperse must not add x to the tail +local intersperse = function(x, gen, param, state) + return wrap(intersperse_gen, {x, gen, param}, {0, state}) +end +methods.intersperse = method1(intersperse) +exports.intersperse = export1(intersperse) + +-------------------------------------------------------------------------------- +-- Compositions +-------------------------------------------------------------------------------- + +local function zip_gen_r(param, state, state_new, ...) + if #state_new == #param / 2 then + return state_new, ... + end + + local i = #state_new + 1 + local gen_x, param_x = param[2 * i - 1], param[2 * i] + local state_x, r = gen_x(param_x, state[i]) + if state_x == nil then + return nil + end + table.insert(state_new, state_x) + return zip_gen_r(param, state, state_new, r, ...) +end + +local zip_gen = function(param, state) + return zip_gen_r(param, state, {}) +end + +-- A special hack for zip/chain to skip last two state, if a wrapped iterator +-- has been passed +local numargs = function(...) + local n = select('#', ...) + if n >= 3 then + -- Fix last argument + local it = select(n - 2, ...) + if type(it) == 'table' and getmetatable(it) == iterator_mt and + it.param == select(n - 1, ...) and it.state == select(n, ...) then + return n - 2 + end + end + return n +end + +local zip = function(...) + local n = numargs(...) + if n == 0 then + return wrap(nil_gen, nil, nil) + end + local param = { [2 * n] = 0 } + local state = { [n] = 0 } + + local i, gen_x, param_x, state_x + for i=1,n,1 do + local it = select(n - i + 1, ...) + gen_x, param_x, state_x = rawiter(it) + param[2 * i - 1] = gen_x + param[2 * i] = param_x + state[i] = state_x + end + + return wrap(zip_gen, param, state) +end +methods.zip = zip +exports.zip = zip + +local cycle_gen_call = function(param, state_x, ...) + if state_x == nil then + local gen_x, param_x, state_x0 = param[1], param[2], param[3] + return gen_x(param_x, deepcopy(state_x0)) + end + return state_x, ... +end + +local cycle_gen = function(param, state_x) + local gen_x, param_x, state_x0 = param[1], param[2], param[3] + return cycle_gen_call(param, gen_x(param_x, state_x)) +end + +local cycle = function(gen, param, state) + return wrap(cycle_gen, {gen, param, state}, deepcopy(state)) +end +methods.cycle = method0(cycle) +exports.cycle = export0(cycle) + +-- call each other +local chain_gen_r1 +local chain_gen_r2 = function(param, state, state_x, ...) + if state_x == nil then + local i = state[1] + i = i + 1 + if param[3 * i - 1] == nil then + return nil + end + local state_x = param[3 * i] + return chain_gen_r1(param, {i, state_x}) + end + return {state[1], state_x}, ... +end + +chain_gen_r1 = function(param, state) + local i, state_x = state[1], state[2] + local gen_x, param_x = param[3 * i - 2], param[3 * i - 1] + return chain_gen_r2(param, state, gen_x(param_x, state[2])) +end + +local chain = function(...) + local n = numargs(...) + if n == 0 then + return wrap(nil_gen, nil, nil) + end + + local param = { [3 * n] = 0 } + local i, gen_x, param_x, state_x + for i=1,n,1 do + local elem = select(i, ...) + gen_x, param_x, state_x = iter(elem) + param[3 * i - 2] = gen_x + param[3 * i - 1] = param_x + param[3 * i] = state_x + end + + return wrap(chain_gen_r1, param, {1, param[3]}) +end +methods.chain = chain +exports.chain = chain + +-------------------------------------------------------------------------------- +-- Operators +-------------------------------------------------------------------------------- + +local operator = { + ---------------------------------------------------------------------------- + -- Comparison operators + ---------------------------------------------------------------------------- + lt = function(a, b) return a < b end, + le = function(a, b) return a <= b end, + eq = function(a, b) return a == b end, + ne = function(a, b) return a ~= b end, + ge = function(a, b) return a >= b end, + gt = function(a, b) return a > b end, + + ---------------------------------------------------------------------------- + -- Arithmetic operators + ---------------------------------------------------------------------------- + add = function(a, b) return a + b end, + div = function(a, b) return a / b end, + floordiv = function(a, b) return math.floor(a/b) end, + intdiv = function(a, b) + local q = a / b + if a >= 0 then return math.floor(q) else return math.ceil(q) end + end, + mod = function(a, b) return a % b end, + mul = function(a, b) return a * b end, + neq = function(a) return -a end, + unm = function(a) return -a end, -- an alias + pow = function(a, b) return a ^ b end, + sub = function(a, b) return a - b end, + truediv = function(a, b) return a / b end, + + ---------------------------------------------------------------------------- + -- String operators + ---------------------------------------------------------------------------- + concat = function(a, b) return a..b end, + len = function(a) return #a end, + length = function(a) return #a end, -- an alias + + ---------------------------------------------------------------------------- + -- Logical operators + ---------------------------------------------------------------------------- + land = function(a, b) return a and b end, + lor = function(a, b) return a or b end, + lnot = function(a) return not a end, + truth = function(a) return not not a end, +} +exports.operator = operator +methods.operator = operator +exports.op = operator +methods.op = operator + +-------------------------------------------------------------------------------- +-- module definitions +-------------------------------------------------------------------------------- + +-- a special syntax sugar to export all functions to the global table +setmetatable(exports, { + __call = function(t, override) + for k, v in pairs(t) do + if rawget(_G, k) ~= nil then + local msg = 'function ' .. k .. ' already exists in global scope.' + if override then + rawset(_G, k, v) + print('WARNING: ' .. msg .. ' Overwritten.') + else + print('NOTICE: ' .. msg .. ' Skipped.') + end + else + rawset(_G, k, v) + end + end + end, +}) + +return exports diff --git a/Data/DefaultContent/Libraries/luafun/rpm/lua-fun.spec b/Data/DefaultContent/Libraries/luafun/rpm/lua-fun.spec new file mode 100644 index 0000000..b200c76 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/rpm/lua-fun.spec @@ -0,0 +1,76 @@ +%define luaver 5.3 +%define luapkgdir %{_datadir}/lua/%{luaver} +# LuaJIT is compatible with Lua 5.1 and uses the same directory for modules +%global ljpkgdir %{_datadir}/lua/5.1 + +Name: lua-fun +Version: 0.1.3 +Release: 1%{?dist} +Summary: Functional programming library for Lua +Group: Development/Libraries +License: MIT +URL: https://github.com/luafun/luafun +Source0: https://github.com/luafun/luafun/archive/%{version}/luafun-%{version}.tar.gz +BuildArch: noarch +BuildRequires: luajit >= 2.0 +BuildRequires: lua >= 5.1 +Requires: lua >= 5.1 + +%package -n luajit-fun +Summary: Functional programming library for LuaJIT +Requires: luajit >= 2.0 + +%description -n lua-fun +Lua Fun is a high-performance functional programming library for Lua +designed with LuaJIT's trace compiler in mind. + +Lua Fun provides a set of more than 50 programming primitives typically +found in languages like Standard ML, Haskell, Erlang, JavaScript, Python and +even Lisp. High-order functions such as map, filter, reduce, zip, etc., +make it easy to write simple and efficient functional code. + +This package provides a module for Lua %{luaver}. + +%description -n luajit-fun +Lua Fun is a high-performance functional programming library for Lua +designed with LuaJIT's trace compiler in mind. + +Lua Fun provides a set of more than 50 programming primitives typically +found in languages like Standard ML, Haskell, Erlang, JavaScript, Python and +even Lisp. High-order functions such as map, filter, reduce, zip, etc., +make it easy to write simple and efficient functional code. + +This package provides a module for LuaJIT. + +%prep +%setup -q -n luafun-%{version} + +%build +# nothing to do + +%install +# Install for Lua +mkdir -p %{buildroot}%{luapkgdir} +cp -av fun.lua %{buildroot}%{luapkgdir}/fun.lua +# Install for LuaJIT +mkdir -p %{buildroot}%{ljpkgdir} +cp -av fun.lua %{buildroot}%{ljpkgdir}/fun.lua + +%check +cd tests +luajit ./runtest *.lua +lua ./runtest *.lua + +%files -n lua-fun +%{luapkgdir}/fun.lua +%doc README.md CONTRIBUTING.md +%license COPYING.md + +%files -n luajit-fun +%{ljpkgdir}/fun.lua +%doc README.md CONTRIBUTING.md +%license COPYING.md + +%changelog +* Mon Jan 18 2016 Roman Tsisyk - 0.1.3-1 +- Initial version. diff --git a/Data/DefaultContent/Libraries/luafun/tests/.gitignore b/Data/DefaultContent/Libraries/luafun/tests/.gitignore new file mode 100644 index 0000000..ce0a7f3 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/tests/.gitignore @@ -0,0 +1 @@ +*.new diff --git a/Data/DefaultContent/Libraries/luafun/tests/basic.lua b/Data/DefaultContent/Libraries/luafun/tests/basic.lua new file mode 100644 index 0000000..97e7aae --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/tests/basic.lua @@ -0,0 +1,332 @@ +-------------------------------------------------------------------------------- +-- iter +-------------------------------------------------------------------------------- + +-- +-- Arrays +-- + +for _it, a in iter({1, 2, 3}) do print(a) end +--[[test +1 +2 +3 +--test]] + +for _it, a in iter(iter(iter({1, 2, 3}))) do print(a) end +--[[test +1 +2 +3 +--test]] + +for _it, a in wrap(wrap(iter({1, 2, 3}))) do print(a) end +--[[test +1 +2 +3 +--test]] + +for _it, a in wrap(wrap(ipairs({1, 2, 3}))) do print(a) end +--[[test +1 +2 +3 +--test]] + +for _it, a in iter({}) do print(a) end +--[[test +--test]] + +for _it, a in iter(iter(iter({}))) do print(a) end +--[[test +--test]] + +for _it, a in wrap(wrap(iter({}))) do print(a) end +--[[test +--test]] + +for _it, a in wrap(wrap(ipairs({}))) do print(a) end +--[[test +--test]] + +-- Check that ``iter`` for arrays is equivalent to ``ipairs`` +local t = {1, 2, 3} +gen1, param1, state1 = iter(t):unwrap() +gen2, param2, state2 = ipairs(t) +print(gen1 == gen2, param1 == param2, state1 == state2) +--[[test +true true true +--test]] + +-- Test that ``wrap`` do nothing for wrapped iterators +gen1, param1, state1 = iter({1, 2, 3}) +gen2, param2, state2 = wrap(gen1, param1, state1):unwrap() +print(gen1 == gen2, param1 == param2, state1 == state2) +--[[test +true true true +--test]] + +-- +-- Maps +-- + +local t = {} +for _it, k, v in iter({ a = 1, b = 2, c = 3}) do t[#t + 1] = k end +table.sort(t) +for _it, v in iter(t) do print(v) end +--[[test +a +b +c +--test]] + +local t = {} +for _it, k, v in iter(iter(iter({ a = 1, b = 2, c = 3}))) do t[#t + 1] = k end +table.sort(t) +for _it, v in iter(t) do print(v) end +--[[test +a +b +c +--test]] + +for _it, k, v in iter({}) do print(k, v) end +--[[test +--test]] + +for _it, k, v in iter(iter(iter({}))) do print(k, v) end +--[[test +--test]] + +-- +-- String +-- + +for _it, a in iter("abcde") do print(a) end +--[[test +a +b +c +d +e +--test]] + +for _it, a in iter(iter(iter("abcde"))) do print(a) end +--[[test +a +b +c +d +e +--test]] + +for _it, a in iter("") do print(a) end +--[[test +--test]] + +for _it, a in iter(iter(iter(""))) do print(a) end +--[[test +--test]] + +-- +-- Custom generators +-- + +local function mypairs_gen(max, state) + if (state >= max) then + return nil + end + return state + 1, state + 1 +end + +local function mypairs(max) + return mypairs_gen, max, 0 +end + +for _it, a in iter(mypairs(10)) do print(a) end +--[[test +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +--test]] + +-- +-- Invalid values +-- + +for _it, a in iter(1) do print(a) end +--[[test +error: object 1 of type "number" is not iterable +--test]] + +for _it, a in iter(1, 2, 3, 4, 5, 6, 7) do print(a) end +--[[test +error: object 1 of type "number" is not iterable +--test]] + +-------------------------------------------------------------------------------- +-- each +-------------------------------------------------------------------------------- + +each(print, {1, 2, 3}) +--[[test +1 +2 +3 +--test]] + +each(print, iter({1, 2, 3})) +--[[test +1 +2 +3 +--test]] + +each(print, {}) +--[[test +--test]] + + +each(print, iter({})) +--[[test +--test]] + +local keys, vals = {}, {} +each(function(k, v) + keys[#keys + 1] = k + vals[#vals + 1] = v +end, { a = 1, b = 2, c = 3}) +table.sort(keys) +table.sort(vals) +each(print, keys) +each(print, vals) +--[[test +a +b +c +1 +2 +3 +--test]] + +each(print, "abc") +--[[test +a +b +c +--test]] + +each(print, iter("abc")) +--[[test +a +b +c +--test]] + +print(for_each == each) -- an alias +--[[test +true +--test]] + +print(foreach == each) -- an alias +--[[test +true +--test]] + +-------------------------------------------------------------------------------- +-- totable +-------------------------------------------------------------------------------- + +local tab = totable(range(5)) +print(type(tab), #tab) +each(print, tab) +--[[test +table 5 +1 +2 +3 +4 +5 +--test]] + +local tab = totable(range(0)) +print(type(tab), #tab) +--[[test +table 0 +--test]] + +local tab = totable("abcdef") +print(type(tab), #tab) +each(print, tab) +--[[test +table 6 +a +b +c +d +e +f +--test]] + +local unpack = rawget(table, "unpack") or unpack +local tab = totable({ 'a', {'b', 'c'}, {'d', 'e', 'f'}}) +print(type(tab), #tab) +each(print, tab[1]) +each(print, map(unpack, drop(1, tab))) +--[[test +table 3 +a +b c +d e f +--test]] + +-------------------------------------------------------------------------------- +-- tomap +-------------------------------------------------------------------------------- + +local tab = tomap(zip(range(1, 7), 'abcdef')) +print(type(tab), #tab) +each(print, iter(tab)) +--[[test +table 6 +a +b +c +d +e +f +--test]] + +local tab = tomap({a = 1, b = 2, c = 3}) +print(type(tab), #tab) +local t = {} +for _it, k, v in iter(tab) do t[v] = k end +table.sort(t) +for k, v in ipairs(t) do print(k, v) end +--[[test +table 0 +1 a +2 b +3 c +--test]] + +local tab = tomap(enumerate("abcdef")) +print(type(tab), #tab) +each(print, tab) +--[[test +table 6 +a +b +c +d +e +f +--test]] diff --git a/Data/DefaultContent/Libraries/luafun/tests/compositions.lua b/Data/DefaultContent/Libraries/luafun/tests/compositions.lua new file mode 100644 index 0000000..7b81d88 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/tests/compositions.lua @@ -0,0 +1,170 @@ +-------------------------------------------------------------------------------- +-- zip +-------------------------------------------------------------------------------- + +dump(zip({"a", "b", "c", "d"}, {"one", "two", "three"})) +--[[test +a one +b two +c three +--test]] + +dump(zip()) +--[[test +--test]] + +dump(zip(range(0))) +--[[test +error: invalid iterator +--test]] + +dump(zip(range(0), range(0))) +--[[test +error: invalid iterator +--test]] + +print(nth(10, zip(range(1, 100, 3), range(1, 100, 5), range(1, 100, 7)))) +--[[test +28 46 64 +--test]] + +dump(zip(partition(function(x) return x > 7 end, range(1, 15, 1)))) +--[[test +8 1 +9 2 +10 3 +11 4 +12 5 +13 6 +14 7 +--test]] + +-------------------------------------------------------------------------------- +-- cycle +-------------------------------------------------------------------------------- + +dump(take(15, cycle({"a", "b", "c", "d", "e"}))) +--[[test +a +b +c +d +e +a +b +c +d +e +a +b +c +d +e +--test]] + + +dump(take(15, cycle(range(5)))) +--[[test +1 +2 +3 +4 +5 +1 +2 +3 +4 +5 +1 +2 +3 +4 +5 +--test]] + +dump(take(15, cycle(zip(range(5), {"a", "b", "c", "d", "e"})))) +--[[test +1 a +2 b +3 c +4 d +5 e +1 a +2 b +3 c +4 d +5 e +1 a +2 b +3 c +4 d +5 e +--test]] + +-------------------------------------------------------------------------------- +-- chain +-------------------------------------------------------------------------------- + +dump(chain(range(2))) +--[[test +1 +2 +--test]] + +dump(chain(range(2), {"a", "b", "c"}, {"one", "two", "three"})) +--[[test +1 +2 +a +b +c +one +two +three +--test]] + +dump(take(15, cycle(chain(enumerate({"a", "b", "c"}), + {"one", "two", "three"})))) +--[[test +1 a +2 b +3 c +one +two +three +1 a +2 b +3 c +one +two +three +1 a +2 b +3 c +--test]] + +local tab = {} +local keys = {} +for _it, k, v in chain({ a = 11, b = 12, c = 13}, { d = 21, e = 22 }) do + tab[k] = v + table.insert(keys, k) +end +table.sort(keys) +for _, key in ipairs(keys) do print(key, tab[key]) end +--[[test +a 11 +b 12 +c 13 +d 21 +e 22 +--test]] + +dump(chain(range(0), range(0), range(0))) +--[[test +error: invalid iterator +--test]] + +dump(chain(range(0), range(1), range(0))) +--[[test +error: invalid iterator +--test]] diff --git a/Data/DefaultContent/Libraries/luafun/tests/filtering.lua b/Data/DefaultContent/Libraries/luafun/tests/filtering.lua new file mode 100644 index 0000000..a5fdfe2 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/tests/filtering.lua @@ -0,0 +1,102 @@ +-------------------------------------------------------------------------------- +-- filter +-------------------------------------------------------------------------------- + +dump(filter(function(x) return x % 3 == 0 end, range(10))) +--[[test +3 +6 +9 +--test]] + +dump(filter(function(x) return x % 3 == 0 end, range(0))) +--[[test +--test]] + + +dump(take(5, filter(function(i, x) return i % 3 == 0 end, + enumerate(duplicate('x'))))) +--[[test +3 x +6 x +9 x +12 x +15 x +--test]] + +function filter_fun(a, b, c) + if a % 16 == 0 then + return true + else + return false + end +end + +function test3(a, b, c) + return a, c, b +end + +n = 50 +dump(filter(filter_fun, map(test3, zip(range(0, n, 1), + range(0, n, 2), range(0, n, 3))))) +--[[test +0 0 0 +16 48 32 +--test]] + +print(remove_if == filter) -- an alias +--[[test +true +--test]] + +-------------------------------------------------------------------------------- +-- grep +-------------------------------------------------------------------------------- + +lines_to_grep = { + [[Lorem ipsum dolor sit amet, consectetur adipisicing elit, ]], + [[sed do eiusmod tempor incididunt ut labore et dolore magna ]], + [[aliqua. Ut enim ad minim veniam, quis nostrud exercitation ]], + [[ullamco laboris nisi ut aliquip ex ea commodo consequat.]], + [[Duis aute irure dolor in reprehenderit in voluptate velit ]], + [[esse cillum dolore eu fugiat nulla pariatur. Excepteur sint ]], + [[occaecat cupidatat non proident, sunt in culpa qui officia ]], + [[deserunt mollit anim id est laborum.]] +} + +dump(grep("lab", lines_to_grep)) +--[[test +sed do eiusmod tempor incididunt ut labore et dolore magna +ullamco laboris nisi ut aliquip ex ea commodo consequat. +deserunt mollit anim id est laborum. +--test]] + +lines_to_grep = { + [[Emily]], + [[Chloe]], + [[Megan]], + [[Jessica]], + [[Emma]], + [[Sarah]], + [[Elizabeth]], + [[Sophie]], + [[Olivia]], + [[Lauren]] +} + +dump(grep("^Em", lines_to_grep)) +--[[test +Emily +Emma +--test]] + +-------------------------------------------------------------------------------- +-- partition +-------------------------------------------------------------------------------- + +dump(zip(partition(function(i, x) return i % 3 == 0 end, range(10)))) +--[[test +3 1 +6 2 +9 4 +--test]] diff --git a/Data/DefaultContent/Libraries/luafun/tests/generators.lua b/Data/DefaultContent/Libraries/luafun/tests/generators.lua new file mode 100644 index 0000000..7a89ebf --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/tests/generators.lua @@ -0,0 +1,287 @@ +-------------------------------------------------------------------------------- +-- range +-------------------------------------------------------------------------------- + +dump(range(0)) +print('--') +for i=1,0 do print(i) end +--[[test +-- +--test]] + +dump(range(0, 0)) +print('--') +for i=0,0 do print(i) end +--[[test +0 +-- +0 +--test]] + +dump(range(5)) +print('--') +for i=1,5 do print(i) end +--[[test +1 +2 +3 +4 +5 +-- +1 +2 +3 +4 +5 +--test]] + +dump(range(0, 5)) +print('--') +for i=0,5 do print(i) end +--[[test +0 +1 +2 +3 +4 +5 +-- +0 +1 +2 +3 +4 +5 +--test]] + +dump(range(0, 5, 1)) +print('--') +for i=0,5,1 do print(i) end +--[[test +0 +1 +2 +3 +4 +5 +-- +0 +1 +2 +3 +4 +5 +--test]] + +dump(range(0, 10, 2)) +print('--') +for i=0,10,2 do print(i) end +--[[test +0 +2 +4 +6 +8 +10 +-- +0 +2 +4 +6 +8 +10 +--test]] + +dump(range(-5)) +print('--') +for i=-1,-5,-1 do print(i) end +--[[test +-1 +-2 +-3 +-4 +-5 +-- +-1 +-2 +-3 +-4 +-5 +--test]] + +dump(range(0, -5, 1)) +print('--') +for i=0,-5,1 do print(i) end +--[[test +-- +--test]] + +dump(range(0, -5, -1)) +print('--') +for i=0,-5,-1 do print(i) end +--[[test +0 +-1 +-2 +-3 +-4 +-5 +-- +0 +-1 +-2 +-3 +-4 +-5 +--test]] + +dump(range(0, -10, -2)) +print('--') +for i=0,-10,-2 do print(i) end +--[[test +0 +-2 +-4 +-6 +-8 +-10 +-- +0 +-2 +-4 +-6 +-8 +-10 +--test]] + +dump(range(1.2, 1.6, 0.1)) +--[[test +1.2 +1.3 +1.4 +1.5 +--test]] + +-- Invalid step +dump(range(0, 5, 0)) +--[[test +error: step must not be zero +--test]] + +-------------------------------------------------------------------------------- +-- duplicate +-------------------------------------------------------------------------------- + +dump(take(5, duplicate(48))) +--[[test +48 +48 +48 +48 +48 +--test]] + +dump(take(5, duplicate(1,2,3,4,5))) +--[[test +1 2 3 4 5 +1 2 3 4 5 +1 2 3 4 5 +1 2 3 4 5 +1 2 3 4 5 +--test]] + +print(xrepeat == duplicate) -- an alias +--[[test +true +--test]] + +print(replicate == duplicate) -- an alias +--[[test +true +--test]] + +-------------------------------------------------------------------------------- +-- tabulate +-------------------------------------------------------------------------------- + +dump(take(5, tabulate(function(x) return 2 * x end))) +--[[test +0 +2 +4 +6 +8 +--test]] + +-------------------------------------------------------------------------------- +-- zeros +-------------------------------------------------------------------------------- + +dump(take(5, zeros())) +--[[test +0 +0 +0 +0 +0 +--test]] + +-------------------------------------------------------------------------------- +-- ones +-------------------------------------------------------------------------------- + +dump(take(5, ones())) +--[[test +1 +1 +1 +1 +1 +--test]] + +-------------------------------------------------------------------------------- +-- rands +-------------------------------------------------------------------------------- + +print(all(function(x) return x >= 0 and x < 1 end, take(5, rands()))) +--[[test +true +--test]] + +dump(take(5, rands(0))) +--[[test +error: empty interval +--test]] + +print(all(function(x) return math.floor(x) == x end, take(5, rands(10)))) +--[[test +true +--test]] + +print(all(function(x) return math.floor(x) == x end, take(5, rands(1024)))) +--[[test +true +--test]] + +dump(take(5, rands(0, 1))) +--[[test +0 +0 +0 +0 +0 +--test]] + +dump(take(5, rands(5, 6))) +--[[test +5 +5 +5 +5 +5 +--test]] + +print(all(function(x) return x >= 10 and x < 20 end, take(20, rands(10, 20)))) +--[[test +true +--test]] diff --git a/Data/DefaultContent/Libraries/luafun/tests/indexing.lua b/Data/DefaultContent/Libraries/luafun/tests/indexing.lua new file mode 100644 index 0000000..febc1ae --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/tests/indexing.lua @@ -0,0 +1,83 @@ +-------------------------------------------------------------------------------- +-- index +-------------------------------------------------------------------------------- + +print(index(2, range(5))) +--[[test +2 +--test]] + +print(index(10, range(5))) +--[[test +nil +--test]] + +print(index(2, range(0))) +--[[test +nil +--test]] + +print(index("b", {"a", "b", "c", "d", "e"})) +--[[test +2 +--test]] + +print(index(1, enumerate({"a", "b", "c", "d", "e"}))) +--[[test +1 +--test]] + +print(index("b", "abcdef")) +--[[test +2 +--test]] + +print(index_of == index) -- an alias +--[[test +true +--test]] + +print(elem_index == index) -- an alias +--[[test +true +--test]] + +-------------------------------------------------------------------------------- +-- indexes +-------------------------------------------------------------------------------- + +dump(indexes("a", {"a", "b", "c", "d", "e", "a", "b", "c", "d", "a", "a"})) +--[[test +1 +6 +10 +11 +--test]] + +dump(indexes("f", {"a", "b", "c", "d", "e", "a", "b", "c", "d", "a", "a"})) +--[[test +--test]] + +dump(indexes("f", {})) +--[[test +--test]] + +dump(indexes(1, enumerate({"a", "b", "c", "d", "e"}))) +--[[test +1 +--test]] + +print(indices == indexes) -- an alias +--[[test +true +--test]] + +print(elem_indexes == indexes) -- an alias +--[[test +true +--test]] + +print(elem_indices == indexes) -- an alias +--[[test +true +--test]] diff --git a/Data/DefaultContent/Libraries/luafun/tests/operators.lua b/Data/DefaultContent/Libraries/luafun/tests/operators.lua new file mode 100644 index 0000000..98ab7bb --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/tests/operators.lua @@ -0,0 +1,322 @@ +-- +-- All these functions are fully covered by Lua tests. +-- This test just checks that all functions were defined correctly. +-- + +print(op == operator) -- an alias +--[[test +true +--test]] + +-------------------------------------------------------------------------------- +-- Comparison operators +-------------------------------------------------------------------------------- + +local comparators = { 'le', 'lt', 'eq', 'ne', 'ge', 'gt' } +for _k, op in iter(comparators) do + print('op', op) + print('==') + print('num:') + print(operator[op](0, 1)) + print(operator[op](1, 0)) + print(operator[op](0, 0)) + print('str:') + print(operator[op]("abc", "cde")) + print(operator[op]("cde", "abc")) + print(operator[op]("abc", "abc")) + print('') +end +--[[test +op le +== +num: +true +false +true +str: +true +false +true + +op lt +== +num: +true +false +false +str: +true +false +false + +op eq +== +num: +false +false +true +str: +false +false +true + +op ne +== +num: +true +true +false +str: +true +true +false + +op ge +== +num: +false +true +true +str: +false +true +true + +op gt +== +num: +false +true +false +str: +false +true +false + +--test]] + +-------------------------------------------------------------------------------- +-- Arithmetic operators +-------------------------------------------------------------------------------- + +print(operator.add(-1.0, 1.0)) +print(operator.add(0, 0)) +print(operator.add(12, 2)) +--[[test +0 +0 +14 +--test]] + +print(operator.div(10, 2)) +print(operator.div(10, 3)) +print(operator.div(-10, 3)) +--[[test +5 +3.3333333333333 +-3.3333333333333 +--test]] + +print(operator.floordiv(10, 3)) +print(operator.floordiv(11, 3)) +print(operator.floordiv(12, 3)) +print(operator.floordiv(-10, 3)) +print(operator.floordiv(-11, 3)) +print(operator.floordiv(-12, 3)) +--[[test +3 +3 +4 +-4 +-4 +-4 +--test]] + +print(operator.intdiv(10, 3)) +print(operator.intdiv(11, 3)) +print(operator.intdiv(12, 3)) +print(operator.intdiv(-10, 3)) +print(operator.intdiv(-11, 3)) +print(operator.intdiv(-12, 3)) +--[[test +3 +3 +4 +-3 +-3 +-4 +--test]] + +print(operator.truediv(10, 3)) +print(operator.truediv(11, 3)) +print(operator.truediv(12, 3)) +print(operator.truediv(-10, 3)) +print(operator.truediv(-11, 3)) +print(operator.truediv(-12, 3)) +--[[test +3.3333333333333 +3.6666666666667 +4 +-3.3333333333333 +-3.6666666666667 +-4 +--test]] + +print(operator.mod(10, 2)) +print(operator.mod(10, 3)) +print(operator.mod(-10, 3)) +--[[test +0 +1 +2 +--test]] + +print(operator.mul(10, 0.1)) +print(operator.mul(0, 0)) +print(operator.mul(-1, -1)) +--[[test +1 +0 +1 +--test]] + +print(operator.neq(1)) +print(operator.neq(0) == 0) +print(operator.neq(-0) == 0) +print(operator.neq(-1)) +--[[test +-1 +true +true +1 +--test]] + +print(operator.unm(1)) +print(operator.unm(0) == 0) +print(operator.unm(-0) == 0) +print(operator.unm(-1)) +--[[test +-1 +true +true +1 +--test]] + +print(operator.pow(2, 3)) +print(operator.pow(0, 10)) +print(operator.pow(2, 0)) +--[[test +8 +0 +1 +--test]] + +print(operator.sub(2, 3)) +print(operator.sub(0, 10)) +print(operator.sub(2, 2)) +--[[test +-1 +-10 +0 +--test]] + +-------------------------------------------------------------------------------- +-- String operators +-------------------------------------------------------------------------------- + +print(operator.concat("aa", "bb")) +print(operator.concat("aa", "")) +print(operator.concat("", "bb")) +--[[test +aabb +aa +bb +--test]] + +print(operator.len("")) +print(operator.len("ab")) +print(operator.len("abcd")) +--[[test +0 +2 +4 +--test]] + +print(operator.length("")) +print(operator.length("ab")) +print(operator.length("abcd")) +--[[test +0 +2 +4 +--test]] + +---------------------------------------------------------------------------- +-- Logical operators +---------------------------------------------------------------------------- + +print(operator.land(true, true)) +print(operator.land(true, false)) +print(operator.land(false, true)) +print(operator.land(false, false)) +print(operator.land(1, 0)) +print(operator.land(0, 1)) +print(operator.land(1, 1)) +print(operator.land(0, 0)) +--[[test +true +false +false +false +0 +1 +1 +0 +--test]] + +print(operator.lor(true, true)) +print(operator.lor(true, false)) +print(operator.lor(false, true)) +print(operator.lor(false, false)) +print(operator.lor(1, 0)) +print(operator.lor(0, 1)) +print(operator.lor(1, 1)) +print(operator.lor(0, 0)) +--[[test +true +true +true +false +1 +0 +1 +0 +--test]] + +print(operator.lnot(true)) +print(operator.lnot(false)) +print(operator.lor(1)) +print(operator.lor(0)) +--[[test +false +true +1 +0 +--test]] + +print(operator.truth(true)) +print(operator.truth(false)) +print(operator.truth(1)) +print(operator.truth(0)) +print(operator.truth(nil)) +print(operator.truth("")) +print(operator.truth({})) +--[[test +true +false +true +true +false +true +true +--test]] diff --git a/Data/DefaultContent/Libraries/luafun/tests/reducing.lua b/Data/DefaultContent/Libraries/luafun/tests/reducing.lua new file mode 100644 index 0000000..8e4aaeb --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/tests/reducing.lua @@ -0,0 +1,289 @@ +-------------------------------------------------------------------------------- +-- foldl +-------------------------------------------------------------------------------- + +print(foldl(function(acc, x) return acc + x end, 0, range(5))) +--[[test +15 +--test]] + +print(foldl(operator.add, 0, range(5))) +--[[test +15 +--test]] + +print(foldl(function(acc, x, y) return acc + x * y; end, 0, + zip(range(1, 5), {4, 3, 2, 1}))) +--[[test +20 +--test]] + +print(reduce == foldl) -- an alias +--[[test +true +--test]] + +-------------------------------------------------------------------------------- +-- length +-------------------------------------------------------------------------------- + +print(length({"a", "b", "c", "d", "e"})) +--[[test +5 +--test]] + +print(length({})) +--[[test +0 +--test]] + +print(length(range(0))) +--[[test +0 +--test]] + +-------------------------------------------------------------------------------- +-- is_null +-------------------------------------------------------------------------------- + +print(is_null({"a", "b", "c", "d", "e"})) +--[[test +false +--test]] + +print(is_null({})) +--[[test +true +--test]] + +print(is_null(range(0))) +--[[test +true +--test]] + +local gen, init, state = range(5) +print(is_null(gen, init, state)) +dump(gen, init, state) +--[[test +false +1 +2 +3 +4 +5 +--test]] + +-------------------------------------------------------------------------------- +-- is_prefix_of +-------------------------------------------------------------------------------- + +print(is_prefix_of({"a"}, {"a", "b", "c"})) +--[[test +true +--test]] + +print(is_prefix_of({}, {"a", "b", "c"})) +--[[test +true +--test]] + +print(is_prefix_of({}, {})) +--[[test +true +--test]] + +print(is_prefix_of({"a"}, {})) +--[[test +false +--test]] + +print(is_prefix_of(range(5), range(6))) +--[[test +true +--test]] + +print(is_prefix_of(range(6), range(5))) +--[[test +false +--test]] + +-------------------------------------------------------------------------------- +-- all +-------------------------------------------------------------------------------- + +print(all(function(x) return x end, {true, true, true, true})) +--[[test +true +--test]] + +print(all(function(x) return x end, {true, true, true, false})) +--[[test +false +--test]] + +print(all(function(x) return x end, {})) +--[[test +true +--test]] + +print(every == all) -- an alias +--[[test +true +--test]] + +-------------------------------------------------------------------------------- +-- any +-------------------------------------------------------------------------------- + +print(any(function(x) return x end, {false, false, false, false})) +--[[test +false +--test]] + +print(any(function(x) return x end, {false, false, false, true})) +--[[test +true +--test]] + +print(any(function(x) return x end, {})) +--[[test +false +--test]] + +print(some == any) -- an alias +--[[test +true +--test]] + +-------------------------------------------------------------------------------- +-- sum +-------------------------------------------------------------------------------- + +print(sum(range(1, 5))) +--[[test +15 +--test]] + +print(sum(range(1, 5, 0.5))) +--[[test +27 +--test]] + +print(sum(range(0))) +--[[test +0 +--test]] + +-------------------------------------------------------------------------------- +-- product +-------------------------------------------------------------------------------- + +print(product(range(1, 5))) +--[[test +120 +--test]] + +print(product(range(1, 5, 0.5))) +--[[test +7087.5 +--test]] + +print(product(range(0))) +--[[test +1 +--test]] + + +-------------------------------------------------------------------------------- +-- min +-------------------------------------------------------------------------------- + +print(min(range(1, 10, 1))) +--[[test +1 +--test]] + +print(min({"f", "d", "c", "d", "e"})) +--[[test +c +--test]] + +print(min({})) +--[[test +error: min: iterator is empty +--test]] + +print(minimum == min) -- an alias +--[[test +true +--test]] + +-------------------------------------------------------------------------------- +-- min_by +-------------------------------------------------------------------------------- + +function min_cmp(a, b) if -a < -b then return a else return b end end +--[[test +--test]] + +print(min_by(min_cmp, range(1, 10, 1))) +--[[test +10 +--test]] + +print(min_by(min_cmp, {})) +--[[test +error: min: iterator is empty +--test]] + +print(minimum_by == min_by) -- an alias +--[[test +true +--test]] + +-------------------------------------------------------------------------------- +-- max +-------------------------------------------------------------------------------- + +print(max(range(1, 10, 1))) +--[[test +10 +--test]] + +print(max({"f", "d", "c", "d", "e"})) +--[[test +f +--test]] + +print(max({})) +--[[test +error: max: iterator is empty +--test]] + +print(maximum == max) -- an alias +--[[test +true +--test]] + +-------------------------------------------------------------------------------- +-- max_by +-------------------------------------------------------------------------------- + +function max_cmp(a, b) if -a > -b then return a else return b end end +--[[test +--test]] + +print(max_by(max_cmp, range(1, 10, 1))) +--[[test +1 +--test]] + +print(max_by(max_cmp, {})) +--[[test +error: max: iterator is empty +--test]] + +print(maximum_by == maximum_by) -- an alias +--[[test +true +--test]] diff --git a/Data/DefaultContent/Libraries/luafun/tests/runtest b/Data/DefaultContent/Libraries/luafun/tests/runtest new file mode 100644 index 0000000..f6774f6 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/tests/runtest @@ -0,0 +1,114 @@ +#!/usr/bin/env lua + +package.path = "../?.lua;"..package.path +require "fun" () +function dump(gen, init, state) each(print, gen, init, state) end + +local unpack = rawget(table, "unpack") or unpack +local loadstring = rawget(_G, "loadstring") or load + +function file_print(file, ...) + local n, i = select("#",...) + for i=1,n do + local x = select(i, ...) + if type(x) == "number" and math.floor(x) == math.ceil(x) then + -- A special hack for Lua 5.3: remove .0 for integer + x = string.match(select(i,...), '^-?%d+') + end + file:write(tostring(x)) + if i~=n then + file:write(' ') + end + end + file:write('\n') +end + +local globals = {} +setmetatable(_G, { + __newindex = function(t,k,v) + local info = debug.getinfo(2, "S") + if info.short_src:sub(1,7) ~= '[string' then + local file = info.short_src + local func = debug.getinfo(2, "n").name or "" + local line = info.linedefined + globals[file..':'..line..':'..k] = {file, line, func, k} + end + rawset(t, k, v) + end +}) + +local function process(test_name) + io.write("Testing ", test_name, "\n") + local new_name = test_name..".new" + local test_file = io.open(test_name, 'r') + local content = test_file:read("*a"); + test_file:close() + + local new_file = io.open(new_name, 'w') + + local prev_print = print + print = function(...) file_print(new_file, ...) end + + io.flush() + local expr + for expr in content:gmatch("(.-)%s*--%[%[test.-test%]%]") do + new_file:write(expr) + new_file:write("\n--[[test\n") + local res, err = loadstring(expr) + if res then + res, err = pcall(res, expr) + end + if not res then + new_file:write('error: ', err:match(".-:%d+:%s*(.*)"), "\n") + end + new_file:write("--test]]") + end + new_file:write("\n") + new_file:close() + + print = prev_print + + local r = os.execute(string.format('diff -U4 "%s" "%s" 2>&1', + test_name, new_name)) + if r then + os.remove(new_name) + return true + else + return false + end +end + +if #arg <= 0 then + io.write("Usage: runtest *.lua", "\n") + os.exit(1) +end + +local failed, i = {} +for i=1,#arg,1 do + local test_name = arg[i] + if not process(test_name) then + table.insert(failed, test_name) + end +end + +if #failed > 0 then + io.write("\n") + io.write("Failed tests:", "\n") + for _k,test_name in ipairs(failed) do + io.write(" ", test_name, "\n") + end + io.write("\n", "Please review *.new files and update tests", "\n") +end + +if next(globals) then + io.write("\n") + io.write("Some global variables have been declared by mistake:", "\n") + for k, pollution in pairs(globals) do + local file, line, func, var = unpack(pollution) + io.write(file..":"..line.." function "..func.."() = var '"..var.."'", "\n") + end + io.write("\n", "Please declare them with the local statement", "\n") +elseif #failed == 0 then + io.write("All tests have passed!", "\n") + os.exit(0) +end diff --git a/Data/DefaultContent/Libraries/luafun/tests/slicing.lua b/Data/DefaultContent/Libraries/luafun/tests/slicing.lua new file mode 100644 index 0000000..c4678c4 --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/tests/slicing.lua @@ -0,0 +1,339 @@ +-------------------------------------------------------------------------------- +-- nth +-------------------------------------------------------------------------------- + +print(nth(2, range(5))) +--[[test +2 +--test]] + +print(nth(10, range(5))) +--[[test +nil +--test]] + +print(nth(2, range(0))) +--[[test +nil +--test]] + +print(nth(2, {"a", "b", "c", "d", "e"})) +--[[test +b +--test]] + +print(nth(2, enumerate({"a", "b", "c", "d", "e"}))) +--[[test +2 b +--test]] + +print(nth(1, "abcdef")) +--[[test +a +--test]] + +print(nth(2, "abcdef")) +--[[test +b +--test]] + +print(nth(6, "abcdef")) +--[[test +f +--test]] + +print(nth(0, "abcdef")) +--[[test +error: invalid first argument to nth +--test]] + +print(nth(7, "abcdef")) +--[[test +nil +--test]] + +-------------------------------------------------------------------------------- +-- head +-------------------------------------------------------------------------------- + +print(head({"a", "b", "c", "d", "e"})) +--[[test +a +--test]] + +print(head({})) +--[[test +error: head: iterator is empty +--test]] + +print(head(range(0))) +--[[test +error: head: iterator is empty +--test]] + +print(head(enumerate({"a", "b"}))) +--[[test +1 a +--test]] + +print(car == head) -- an alias +--[[test +true +--test]] + +-------------------------------------------------------------------------------- +-- tail +-------------------------------------------------------------------------------- + +dump(tail({"a", "b", "c", "d", "e"})) +--[[test +b +c +d +e +--test]] + +dump(tail({})) +--[[test +--test]] + +dump(tail(range(0))) +--[[test +--test]] + +dump(tail(enumerate({"a", "b"}))) +--[[test +2 b +--test]] + +print(cdr == tail) -- an alias +--[[test +true +--test]] + + +-------------------------------------------------------------------------------- +-- take_n +-------------------------------------------------------------------------------- + +dump(take_n(0, duplicate(48))) +--[[test +--test]] + +dump(take_n(5, range(0))) +--[[test +--test]] + +dump(take_n(1, duplicate(48))) +--[[test +48 +--test]] + +dump(take_n(5, duplicate(48))) +--[[test +48 +48 +48 +48 +48 +--test]] + +dump(take_n(5, enumerate(duplicate('x')))) +--[[test +1 x +2 x +3 x +4 x +5 x +--test]] + +-------------------------------------------------------------------------------- +-- take_while +-------------------------------------------------------------------------------- + +dump(take_while(function(x) return x < 5 end, range(10))) +--[[test +1 +2 +3 +4 +--test]] + +dump(take_while(function(x) return x < 5 end, range(0))) +--[[test +--test]] + +dump(take_while(function(x) return x > 100 end, range(10))) +--[[test +--test]] + +dump(take_while(function(i, a) return i ~=a end, enumerate({5, 2, 1, 3, 4}))) +--[[test +1 5 +--test]] + +-------------------------------------------------------------------------------- +-- take +-------------------------------------------------------------------------------- + +dump(take(function(x) return x < 5 end, range(10))) +--[[test +1 +2 +3 +4 +--test]] + +dump(take(5, duplicate(48))) +--[[test +48 +48 +48 +48 +48 +--test]] + +-------------------------------------------------------------------------------- +-- drop_n +-------------------------------------------------------------------------------- + +dump(drop_n(5, range(10))) +--[[test +6 +7 +8 +9 +10 +--test]] + +dump(drop_n(0, range(5))) +--[[test +1 +2 +3 +4 +5 +--test]] + +dump(drop_n(5, range(0))) +--[[test +--test]] + +dump(drop_n(2, enumerate({'a', 'b', 'c', 'd', 'e'}))) +--[[test +3 c +4 d +5 e +--test]] + +-------------------------------------------------------------------------------- +-- drop_while +-------------------------------------------------------------------------------- + +dump(drop_while(function(x) return x < 5 end, range(10))) +--[[test +5 +6 +7 +8 +9 +10 +--test]] + +dump(drop_while(function(x) return x < 5 end, range(0))) +--[[test +--test]] + +dump(drop_while(function(x) return x > 100 end, range(10))) +--[[test +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +--test]] + +dump(drop_while(function(i, a) return i ~=a end, enumerate({5, 2, 1, 3, 4}))) +--[[test +2 2 +3 1 +4 3 +5 4 +--test]] + +dump(drop_while(function(i, a) return i ~=a end, + zip({1, 2, 3, 4, 5}, {5, 4, 3, 2, 1}))) +--[[test +3 3 +4 2 +5 1 +--test]] + +-------------------------------------------------------------------------------- +-- drop +-------------------------------------------------------------------------------- + +dump(drop(5, range(10))) +--[[test +6 +7 +8 +9 +10 +--test]] + +dump(drop(function(x) return x < 5 end, range(10))) +--[[test +5 +6 +7 +8 +9 +10 +--test]] + + +-------------------------------------------------------------------------------- +-- span +-------------------------------------------------------------------------------- + +dump(zip(span(function(x) return x < 5 end, range(10)))) +--[[test +1 5 +2 6 +3 7 +4 8 +--test]] + +dump(zip(span(5, range(10)))) +--[[test +1 6 +2 7 +3 8 +4 9 +5 10 +--test]] + +dump(zip(span(function(x) return x < 5 end, range(0)))) +--[[test +--test]] + +dump(zip(span(function(x) return x < 5 end, range(5)))) +--[[test +1 5 +--test]] + +print(split == span) -- an alias +--[[test +true +--test]] + +print(split_at == span) -- an alias +--[[test +true +--test]] diff --git a/Data/DefaultContent/Libraries/luafun/tests/transformations.lua b/Data/DefaultContent/Libraries/luafun/tests/transformations.lua new file mode 100644 index 0000000..b4fddab --- /dev/null +++ b/Data/DefaultContent/Libraries/luafun/tests/transformations.lua @@ -0,0 +1,107 @@ +-------------------------------------------------------------------------------- +-- map +-------------------------------------------------------------------------------- + +fun = function(...) return 'map', ... end + +dump(map(fun, range(0))) +--[[test +--test]] + + +dump(map(fun, range(4))) +--[[test +map 1 +map 2 +map 3 +map 4 +--test]] + +dump(map(fun, enumerate({"a", "b", "c", "d", "e"}))) +--[[test +map 1 a +map 2 b +map 3 c +map 4 d +map 5 e +--test]] + +dump(map(function(x) return 2 * x end, range(4))) +--[[test +2 +4 +6 +8 +--test]] + +fun = nil +--[[test +--test]] + +-------------------------------------------------------------------------------- +-- enumerate +-------------------------------------------------------------------------------- + +dump(enumerate({"a", "b", "c", "d", "e"})) +--[[test +1 a +2 b +3 c +4 d +5 e +--test]] + +dump(enumerate(enumerate(enumerate({"a", "b", "c", "d", "e"})))) +--[[test +1 1 1 a +2 2 2 b +3 3 3 c +4 4 4 d +5 5 5 e +--test]] + +dump(enumerate(zip({"one", "two", "three", "four", "five"}, + {"a", "b", "c", "d", "e"}))) +--[[test +1 one a +2 two b +3 three c +4 four d +5 five e +--test]] + +-------------------------------------------------------------------------------- +-- intersperse +-------------------------------------------------------------------------------- + +dump(intersperse("x", {})) + +dump(intersperse("x", {"a", "b", "c", "d", "e"})) +--[[test +a +x +b +x +c +x +d +x +e +x +--test]] + +dump(intersperse("x", {"a", "b", "c", "d", "e", "f"})) +--[[test +a +x +b +x +c +x +d +x +e +x +f +x +--test]] -- cgit v1.1-26-g67d0