Expressions language for Clojure(Script) and JavaScript inspired by Microsoft Excel ™
In some applications, the lion's share of business logic is concentrated in dynamic expressions. Often they are not even part of the code base and are stored in a database, files, or somewhere in the cloud. And sometimes these expressions need to be accessed non-technical personnel, like managers or call centers operators. Making them learn clojure or python is not fair. This library is designed to combine the best of two completely different worlds: the most understandable syntax from Excel and the speed of Clojure.
[io.xapix/axel-f "2.0.11"]
(set-env! :dependencies #(conj % [io.xapix/axel-f "2.0.11"]))
{:deps {io.xapix/axel-f {:mvn/version "2.0.11"}}}
Please checkout the documentation for JavaScript package
(require '[axel-f.excel :as axel-f])
;; Compile Excel-like formula into executable function
(def foo (axel-f/compile "AVERAGE({1, 2, 3})"))
(foo)
;; => 2
((axel-f/compile "SUM(1, 2, AVERAGE({4,5,6}), foo.bar, foo.baz[*].x)")
{:foo {:bar 1
:baz [{:x 5}
{:x 7}
{:x 8}]}})
;; => 29
;; metadata of compiled functions has information about used variables
(meta (axel-f/compile "SUM(1, 2, AVERAGE({4,5,6}), foo.bar, foo.baz[*].x)"))
;; => {:free-variables (("foo" "bar") ("foo" "baz" "*" "x")) ... }
MAP
, FILTER
, SORT
, LENGTH
, CONCAT
FN(x, y, x + y)
where all but last arguments are arglist, last - lambda's body with local bindings.In addition to a formula, the run function can accept execution context as a second argument. Context can be any valid Clojure(Script) object. In the formula you can select the data from context by using object reference operators:
foo.bar.baz
.'some string with spaces'
foo[*].bar
foo[*][*]
we support nested vectors (vector of vectors of vectors ...)foo[*].bar[*].baz
foo[1].bar
foo[SUM(x, 10)].bar
'bar > baz'[0].foo
or 'foo -> bar'.baz
FILTER
or SORT
possibly can return nested data structure and this data can be used as a root reference object: FILTER(FN(item, item.x), _)[0].x
with context [{:x 2} {:x 1} {:x 3}]
returns 1
as expected.True/False/true/false
'Some String'
, "Some String"
){1, 2, TRUE}
)Any expression can be used as an operand for any operator. axel-f has the same operator precedence as in Excel. To change a precendence of operators you can use round brackets ((2+2)*2
=> 8)
-/+
, eg. "-1") Can be used for coercing boolean into number (--TRUE
=> 1)2.4%
) axel-f uses float as replacement (2.4%
=> 0.024).+/-
)* and /
)>
)>=
)<
)<=
)=
)<>
)^
)&
)Please check the wiki page
MAP
, FILTER
, SORT
no longer accept reference as a first argument. Use lambda function instead.CONCAT
to concatenate elements of multiple collections.To be more data-driven def-excel-fn
was replaced by providing extra context to
compile
function. It must be a map of token -> fn pairs.
New special function WITH
can be used to create local bindings.
E.g.
WITH(x, 1,
y, 2,
x + y)
=> 3
Lambdas also supported here
WITH(foo, FN(x, x + 2),
MAP(foo, {5, 6, 7}))
=> [7, 8, 9]
Copyright © 2018 Xapix GmbH, and contributors
Distributed under the Eclipse Public License, the same as Clojure.
Can you improve this documentation? These fine people already did:
Kirill Chernyshov & Christopher KlausEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close