complexpr
complexpr
is an expression evaluator written in Rust. It inlcudes native support for ratios and complex numbers, list oeprations, a large library of functions, and syntax for defining new functions inside expressions.
Types
All values are stored as variants of the complexpr::value::Value
enum.
Integer(i64)
- a 64-bit signed integerFloat(f64)
- a 64-bit floating point numberComplex(num::complex::Complex<f64>)
- a complex number composed of two floatsRatio(num::rational::Ratio<i64>)
- a ratio of two signed integersBool(bool)
- a boolean valueList(Vec<Value>)
- a list of valuesStr(String)
- a stringFunction(complexpr::function::Function)
- a Rust function callable from inside expressionsLambda{..}
- a function created inside an expression
The Value
enum implements the +
, -
, *
, /
, and %
operators in Rust, as well as equality, comparison, and the functions pow
and frac
. It also implements other utility functions.
Syntax
Literals
The following literals are supported:
- integers -
\d+
- floats -
\d+\.\d*|\.\d+
(at least one digit and exactly one.
) - imaginary numbers -
\d+(\.\d*)?i|\.\d+i
(integer or float followed byi
) - true and false -
true|false
- strings -
"(?:[^"\\]|\\[\\"nrt0]|\\u\{[0-9a-fA-F]+\}|\\x[0-9a-fA-F]{2})*"
(see below)
String literals
String literals must begin and end with a double quote ("
). The body of a string literal is a sequence of the following:
- any character besides
"
or\
- The escape sequences
\"
(double quote),\\
(backslash),\n
(newline),\r
(carriage return),\t
(tab),\0
(null),\e
(escape, hex code0x1b
) - The escape sequence
\x
followed by two hex digits (unicode character by hex value) - The escape sequence
\u
, followed by a series of hex digits surrounded by curly braces (unicode character by hex value), example:\u{1F41F}
(🐟)
Operators
Binary operators:
+
- addition, string concatenation, list concatenation, booleanor
-
- subtraction*
- multiplication, booleanand
/
- division^
- exponentiation, booleanxor
//
- fraction%
- modulo (remainder after division)>
,<
,>=
,<=
- greater than, less than, greater or equal, less or equal==
,!=
- equal, not equal
Assignment operators:
=
- assignment+=
,-=
,*=
,/=
,%=
- compound assignments
Unary operators:
-
- negation, booleannot
Other:
,
- separate expressions in a list;
- separate expressions in a block:
- lambda expression
It's not a bug, it's a feature!
Function calls where the only argument is a list "unpack" that list into arguments. For example: foo(1, 2, 3)
is equivalent to foo((1, 2, 3))
. This can be prevented by adding a comma at the end of the function arguments (foo((1,2,3),)
Lambda expressions cannot directly call themselves, even when assigned to a variable. For example, foo = x:foo(x)
fails on call because foo
is unset. It is usually better to use a builtin function for this (loop
, iter
, seq
, etc). If needed, however, this can be circumvented by having the function take another function as an argument (foo = (bar,x):bar(x)
) and then creating a second function that calls the first with itself (real_foo = x:foo(foo, x)
)