Compared to other Lisps, GameLisp's numbers are relatively simple. A number may only be an
(a 32-bit signed integer) or a
flo (a 32-bit IEEE float). Rational fractions, arbitrary-precision
integers and complex numbers are not supported.
The API for manipulating numbers is mostly unsurprising - the full list of functions is available here. Some minor points:
Bit manipulation is supported for integers.
We provide a simple random number generator.
There is a distinction between
-1for any number) and
flo‑sign(which returns the sign of a float as
(prn (sign -0.0)) ; prints 0 (prn (flo-sign -0.0)) ; prints -1.0
Floats are "contagious". When a function such as
+ receives both an integer and a
float among its arguments, the integer is promoted to a float before performing the operation, so
the return value is always a float.
(prn (+ 1 2 3 4)) ; prints 10 (prn (+ 1 2 3.0 4)) ; prints 10.0 (prn (/ 7 2)) ; prints 3 (prn (/ 7 2.0)) ; prints 3.5 (prn (% 5 1.5)) ; prints 0.5
clamp are the exception to the rule, because they return one of
their arguments unchanged.
(prn (max 1 2 3.0 4)) ; prints 4 (prn (clamp 1.0 3 5.0)) ; prints 3
Integer arithmetic is always unchecked (wrapping), even when your crate is compiled in debug mode.
(prn (+ 1 2147483647)) ; prints -2147483648
This helps to keep the language simple. If GameLisp were to take Rust's approach to integer overflow, it would need to provide distinct APIs for normal, wrapping and checked arithmetic. In Rust, this adds a large complexity burden when working with integers.
Out of those three options, wrapping arithmetic was chosen over checked arithmetic in order to make fatal errors less likely. In game development, overflowing an entity's coordinates and getting a nonsensical value will usually be a minor bug, but overflowing an entity's coordinates and crashing the game's executable would be catastrophic.