Meaning: to compute in Poleese
Pronunciation: lee-ming (g as in mingle)
LMAπ embaldens you to write safe and efficient software in an ergonomic manner. It does so in a number of ways, most important of them being:
- Dynamic typing, ridding you of nosy compilers.
- Weak typing, so that it works even if the types donβt match exactly.
- Implicit opening bracket in contexts where itβs possible, that being loops, function definitions and such, so that you donβt waste time arguing about a newline preceding it (inspired by Zimbu).
- No brackets at all around arguments in call expressions, because itβs tedious to write those. Same goes for any other delimiter and separator that the compiler can reasonably deduce.
- Easy to remember and internalize arithmetics. No more PEMDAS. No need to check precedence rules in the documentation. All binary operators parse right to left - always.
However, the largest advantage of LMAπ compared to any other language is its readability. In this regard, it outclasses even Rust. Such feat could only be achieved using two novel approaches:
- All keywords are carefully selected emoji. This makes them easily distinguishable, as you donβt need to parse a sequence of latin letters - or worse - other, even more abstract symbols. Instead, the most primitive part of your brain can instantly process the image on your screen and conclude that before you stands a bald person
π§βπ¦²
(not to confuse with bald manπ¨βπ¦²
or bald womanπ©βπ¦²
). Thatβs when you know a block is being closed, and can proceed with spending your precious brainpower on tasks far more constructive than staring at this strangely shaped squiggle:}
. - The code is indented using the most natural approach - Fibonacci Indentation. Close to the left border of your text-editing widget small differences are easily distinguished, hence even 1-space indent is sufficient. The farther to the right you look, the harder it is to follow the code without the reference of the previously mentioned border. Thusly, the indentation should be more pronounced, which is exactly what Fibonacci Indentation achieves. Moreover, the relative lengths of indentation levels will approach the golden ratio, which makes the bright code on your screen much easier on your eyes.
Examples are the best way to start coding in a new language, especially one as simple as LMAπ. Consider the following program that writes βHello Worldβ to the standard output and exits:
ππ£π§΅Hello Worldπ§΅
Letβs break it down.
π
evaluates expressions to its right, assumes that the first one is a function and then calls it, forwarding all other values to the callee.
π£
is a built-in function that takes any number of arguments and prints them in a single line.
π§΅β¦π§΅
creates a string variable containing the characters between spools.
That was easy, huh? Letβs throw some flow control in there and compute a couple elements of the Fibonacci Sequence:
π¦
πΆ fib = π§° n β‘οΈ
βn < 2
1
π§βπ¦²π‘
πΆ π
°οΈ = πfibπ¦n - 1π§β𦲠πͺ
πΆ π
±οΈ = πfibπ¦n - 2π§β𦲠πͺ
π
°οΈ+π
±οΈ
π§βπ¦²
π§βπ¦²πͺ
ππ£ πfib 0 πͺ
ππ£ πfib 1 πͺ
ππ£ πfib 5 πͺ
ππ£ πfib 30 πͺ
π§βπ¦²
Iβm sure you already figured out whatβs happening, so Iβll be quick:
First of all, we have a couple of distinct expressions, so the program needs to be put in a block. This block must be explicit and is opened by π¦
at the beginning. The closing token is π§βπ¦²
at the end.
Inside of it you will notice multiple πͺ
, those separate expressions in a block. Also, the value of the last expression in the block becomes the entire blockβs value. So, what expressions are there?
πΆ fib = π§° n β‘οΈ
βn < 2
1
π§βπ¦²π‘
πΆ π
°οΈ = πfibπ¦n - 1π§β𦲠πͺ
πΆ π
±οΈ = πfibπ¦n - 2π§β𦲠πͺ
π
°οΈ+π
±οΈ
π§βπ¦²
π§βπ¦²
That too is a new concept, πΆ X=Y
creates a new, baby-variable named X
and with the value obtained by evaluating the Y
expression. The token starting said expression is π§°
, a toolbox. Thatβs no coincidence, it is a function, a new tool of ours! This tool takes a single argument - n
- and maps (β‘οΈ
) it to a new value.
What might this value be, you wonder. Do not fret β the function wonders as well, hence the β
-expression that executes two different blocks depending on the logical state of its condition (n < 2
). If it is fulfilled, the block that trivially evaluates to 1
is executed. If itβs not, then the unhappy path (π‘
) takes place and we have some more work to do:
πΆ π
°οΈ = πfibπ¦n - 1π§β𦲠πͺ
πΆ π
±οΈ = πfibπ¦n - 2π§β𦲠πͺ
π
°οΈ+π
±οΈ
But you already know all of this - we first create two new variables (π
°οΈ
and π
±οΈ
) with values of the fib
function evaluated at n-1
and n-2
. The n-X
sub-expressions are wrapped in blocks, as otherwise the expression would be evaluated as π¦πfib nπ§β𦲠- 1
. Then the block evaluates to the last expression, that being the sum π
°οΈ+π
±οΈ
.
The rest is trivial. We have a couple expressions of the form:
ππ£ πfib N πͺ
But this is just a nested function call - we call π£
passing to it the result of calling fib with a single argument - N
.
As you must have noticed, we have more tokens that close blocks (π§βπ¦²
) than we do those that open them (π¦
). As was explained in the about section, opening a block is often implied. In this program it happened for β
, π‘
and π§°
. Other expressions that make use of this feature are π
(angry-but-not-very-much β
path, sometimes referred to as elif
) and π
(premature exit from a block, similar to break
in other languages).
If you'd like to see some more samples of LMAπ, take a look at the examples/
folder. There are no comments of course, as the language is way too readable for them to be useful. To run them, use carg run --release --bin lmang-exec -- ./examples/β¦.π
TODO