Arc Forumnew | comments | leaders | submitlogin
Readable arithmetics?
1 point by DmitriLebedev 6071 days ago | 4 comments
I wonder if there are implementations of methods to write readable arithmetics in lisp/arc.

I'm learning cl by trying to implement something small and interesting and wrote a code to get Google Maps tile for a given (lat lon zoom). To convert latitude into mercator latitude I had to write the following:

(- (log (tan (+ (/ pi 4) (/ (radians lat) 2)))))))

in php it would look like

which is -log(tan(pi/4 + radians(lat)/2)) in maths.

Why not make a function to parse such expressions and evaluate them? The second expression can be valid lisp code, and the code may look like

(arith '(- log (tan (pi / 4 + radians (lat) / 2)))

I've written a code to parse simple sequenses, like 2 ^ 2 + 2 * 3 ^ 4 (still without parenthesis), but maybe it is already done?

    (defun get-op (elem ops)
        (cond
            ((atom ops) (if (equal elem ops) elem nil))
            ((equal elem (car ops)) (car ops))
            (t (get-op elem (cdr ops)))))

    (defun do-ops (expr ops)
        (print expr)
        (cond 
            ((atom expr) expr)
            ((= (length expr) 1) (car expr))
            ((get-op (cadr expr) ops)
                (do-ops
                    (cons
                        (funcall
                        (cadr expr)
                        (do-ops (car expr) ops)
                        (do-ops (cddr expr) ops))
                        (cdddr expr))
                    ops))
            (t (cons
                    (car expr)
                    (list (cadr expr)
                    (do-ops (cddr expr) ops))))))

    (do-ops '(5) '(+))
    (do-ops '(5 + 2) '(+))
    (do-ops (do-ops '(5 + 2 * 3) '(*)) '(+))


4 points by absz 6071 days ago | link

Since this is the Arc forum, I can link you to the Arc solution: http://arclanguage.org/item?id=3477 . It's a general way to set up infix notation for arithmetic, etc.

-----

2 points by DmitriLebedev 6070 days ago | link

Great, thank you very much. I didn't know the keyword "infix".

-----

3 points by eds 6070 days ago | link

Just FYI, 'infix is not a keyword. (Arc doesn't really have keywords in the same way as other languages, the closest it has are words like 'quote, 'fn, and 'if, which need to be dealt with explicitly in the compiler. Things like 'def and '= which look like keywords in other languages are actually macros, allowing them to be (re)defined by the user inside of arc.)

Also note that there is an infix syntax (besides the custom DSL solution mentioned above), which would probably do what you want. (See http://arclanguage.org/item?id=2610.) You can

  arc> (load "lib/infix.arc")
  nil
after which, the infix form

  (- (log (tan (pi / 4 + (radians lat) / 2)))
would be equivalent to

  (- (log (tan (+ (/ pi 4) (/ (radians lat) 2)))))))
Note that using infix.arc, you don't even need an 'infix keyword around infix math. (This works as long as the object in functional position is a number.) Also note that the syntax of function calls is still exactly the same, it is just infix notation that is implemented.

Because infix notation doesn't interfere with the rest of the language, it actually used to be loaded by default on Anarki, but it was removed because it incurs a fairly hefty runtime overhead, even when using normal (prefix) math.

-----

1 point by Johnny_65701 6065 days ago | link

This question is not language-specific. I've written run-time equation evaluators in C before, and basically what you have to do is convert infix to postfix (aka "reverse Polish" notation), then execute the postfix. You can find easy algorithms online to do both these things. Postfix expressions are evaluated using a stack, and it is very easy to write code to do this.

-----