masak / alma

ALgoloid with MAcros -- a language with Algol-family syntax where macros take center stage
Artistic License 2.0
137 stars 15 forks source link

Linear equation in, solution out #268

Open masak opened 7 years ago

masak commented 7 years ago

I don't know why I didn't think of this one long ago:

my x = solve(3 * x + 4 == 25);
say(x);    # 7

The macro solve would recognize linear equations (and die on anything else), then do symbolic manipulation to arrive at the exact solution.

Actually the main idea here is to use an expression AST for something other than simply computing an expression. Here we're solving on the expression instead. The idea here comes from Smalltalk, where it's apparently standard practice to do fun things with the AST besides just plain evaluating it.

If we have fractions, the returned x could be a fraction, otherwise it could simply be a string.

If we get this one working, we could take a stab at quadratic equations.

masak commented 6 years ago

In 007, the following is allowed:

my x = x;

And in general, using a variable before it has been given a value is something the 007 compiler doesn't complain about — but the linter is meant to.

It'd make sense for solve() to maybe register somehow with the Linter API that using a variable like that is fine, so that the linter doesn't spuriously warn on a line like the one in the OP.

masak commented 6 years ago

On second thought I prefer the syntax of the macro to be more that of a function expression:

say(solve -> x {
    3 * x + 4 == 25
});

This introduces x as a block parameter to the scope where it's used. It also untangles "the x in our mainline scope" from "the x in solve" by having only the latter.

I don't know if it's good or bad that I always end up converging on macros that are extremely virtuous with lexical scoping. I think it reflects on my preferences more than on what's theoretically possible.