help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to improve the readability of (any) LISP or any highlevel functi


From: Pascal J. Bourguignon
Subject: Re: How to improve the readability of (any) LISP or any highlevel functional language to the level of FORTH ?
Date: Thu, 06 Jan 2011 20:20:50 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux)

Doug Hoffman <glidedog@gmail.com> writes:

> 2) The following is one way (of many) to approach this in standard Forth:
>
> : quad f{ a b c -- root }
>   b FNEGATE b FDUP F* 4e a c F* F* F- FSQRT F+ 2e a F* F/
>   ;
>
> -2e 7e 15e quad f.
> -1.500000
>
> Is it readable?  Unless you're a Forther I would say no.  But notice
> the complete lack of parentheses and operator precedences to resolve.
> Any competent Forther could quickly see exactly what is going on.

Now, as a Forth programmer, ask yourself what you would have to do, to
call an operator with a variable arity?

In Postscript, there is a mark operator, to push a mark on the stack, so
that a next operator of variable arity may collect a variable number of
arguments, up to that mark.

Then, as a Forth programmer, ask yourself what you would need to be able
to parse a Forth expression containing unknown operators, ie. operators
of unknown (possibly fixed, but also variable) arity?]

If you consider a separate table giving the arity of the operators, then
it is not unknown anymore.  The only solution I know, is to use mark
systematically:


  MARK MARK MARK MARK MARK b FNEGATE FDUP F* MARK 4e a c F* F- FSQRT F+
  MARK 2e a F* F/

Then, we may add some syntactic sugar, replacing call the MARK operator
'(', and adding gratuituous balanced ')' after each operator:

  (((((((b -) FDUP) f*) (4e a c F*) F-) FSQRT) F+) (2e a F*) F/)

Finally, we may apply mechanically a recursive reverse:

    (defun rrev (x)
      (if (listp x)
         (mapcar 'rrev (reverse x))
         x))

    (rrev 
      '(((((((b -) FDUP) f*) (4e a c F*) F-) FSQRT) F+) (2e a F*) F/))

   (F/ (F* a 2e)
       (F+ (FSQRT (F- (F* c a 4e)
                      (F* (FDUP (- b)))))))

so it becomes readable again and you can see there's a bug in the Forth
expression.    Since the syntax become suddenly much simplier, we don't
need to prefix operators with 'F' anymore. So we can write merely:


   (/ (* a 2)
      (+ (sqrt (- (* c a 4)
                  (* (dup (- b)))))))

Anyways, the great thing now, is that we have homoiconicity
(notice how I used the parenthesised source expression as data passed
to rrev), and we can process expressions without knowing the arity of
the operators (the operators may even not be defined before we process
expressions using them!).  For example, we could now write:

    (derivate '(/ (* a 2)
                  (+ (sqrt (- (* c a 4)
                              (* (dup (- b)))))))
              'a)
and get:

    --> (- (/ 2 (sqrt (- (* 4 a c) (* b b))))
           (/ (* 4 a c) (expt (sqrt (- (* 4 a c) (* b b))) 3/2)))

and since this is one of the first applications of Lisp, you can see now
the reasons and advantages why lisp has these parentheses.  Of course,
that doesn't preclude writing in lisp symbolic mathematic programs like
maxima, providing the mathematical user with a more usual infix input
and 2D output:

    http://www.informatimago.com/images/example-maxima.png


> 3) We have available in Forth a FORmula TRANslator utility (it is not
> part of the official ANS Forth standard).  It could be applied in this
> situation as follows:
>
> : quad2 f{ a b c -- root }
>   f' (-b + sqrt(b^2 - 4*a*c))/(2*a)'
>   ;

There are also infix-to-lisp utilities to embed infix expressions in
lisp program.  If you had to implement a program with a lot of
mathematical formula to copy from a book, I guess these utility would
come handy.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]