From: Mark Tarver
Subject: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <1184062012.334828.176410@22g2000hsm.googlegroups.com>
This test was conducted to determine the relative efficiency of hand-
coded Lisp, OCaml, Qi 8.0 and Qi Turbo-E using the benchmark challenge
provided by Jon Harrop.  Dr Harrop also provided the
Lisp source written by Andre Thieme, Nathan Forster and Pascal
Constanza.

Turbo-E is an unreleased version of Qi which factorises its pattern-
matching.

Jon Harrop Challenge Problem
--------------------------------------------

Posted by Dr Harrop

http://groups.google.co.uk/group/comp.lang.lisp/browse_thread/thread/e69f2854fe5d19b5/a3ba5d7372a05917?lnk=gst&q=nathan+harrop+thieme&rnum=1&hl=en#a3ba5d7372a05917

The problem is to simplify symbolic expressions by applying the
following rewrite rules from the leaves up:

rational n + rational m -> rational(n + m)
rational n * rational m -> rational(n * m)
symbol x -> symbol x
0+f -> f
f+0 -> f
0*f -> 0
f*0 -> 0
1*f -> f
f*1 -> f
a+(b+c) -> (a+b)+c
a*(b*c) -> (a*b)*c

The Solutions
--------------------

Language: Qi
Author: Mark Tarver
Length: 13 lines

(define simplify
  [Op A B] -> (s [Op (simplify A) (simplify B)])
  A -> A)

(define s
  [+ M N] -> (+ M N)	where (and (number? M) (number? N))
  [+ 0 F] -> F
  [+ F 0] -> F
  [+ A [+ B C]] -> [+ [+ A B] C]
  [* M N] -> (* M N)	where (and (number? M) (number? N))
  [* 0 F] -> 0
  [* F 0] -> 0
  [* A [* B C]] -> [[A * B] * C]
  A -> A)

* Note I have used prefix notation for this problem though Dr Harrop's
formulation uses infix. It does make a lot of difference to the
timings. The Lisp solutions follow prefix and so I chose to make my
program comparable.*

*********************************************************
Language: OCaml
Author: Jon Harrop
Length: 15 lines

let rec ( +: ) f g = match f, g with
  | `Int n, `Int m -> `Int (n +/ m)
  | `Int (Int 0), e | e, `Int (Int 0) -> e
  | f, `Add(g, h) -> f +: g +: h
  | f, g -> `Add(f, g)


let rec ( *: ) f g = match f, g with
  | `Int n, `Int m -> `Int (n */ m)
  | `Int (Int 0), e | e, `Int (Int 0) -> `Int (Int 0)
  | `Int (Int 1), e | e, `Int (Int 1) -> e
  | f, `Mul(g, h) -> f *: g *: h
  | f, g -> `Mul(f, g)


let rec simplify = function
  | `Int _ | `Var _ as f -> f
  | `Add (f, g) -> simplify f +: simplify g
  | `Mul (f, g) -> simplify f *: simplify g
********************************************************************
Language: Lisp
Author: Andre Thieme
Length: 23 lines

(defun simplify (a)
   (if (atom a)
       a
       (destructuring-bind (op x y) a
        (let* ((f (simplify x))
               (g (simplify y))
               (nf (numberp f))
               (ng (numberp g))
               (+? (eq '+ op))
               (*? (eq '* op)))
          (cond
            ((and +? nf ng)                   (+ f g))
            ((and +? nf (zerop f))            g)
            ((and +? ng (zerop g))            f)
            ((and (listp g) (eq op (first g)))
             (destructuring-bind (op2 u v) g
               (simplify `(,op (,op ,f ,u) ,v))))
            ((and *? nf ng)                   (* f g))
            ((and *? (or (and nf (zerop f))
                         (and ng (zerop g)))) 0)
            ((and *? nf (= 1 f))              g)
            ((and *? ng (= 1 g))              f)
            (t                                `(,op ,f ,g)))))))

********************************************************************
Language: Lisp
Author: Nathan Froyd
Length: 42 lines

(defun simplify-no-redundant-checks (xexpr)
  (declare (optimize (speed 3)))
  (if (atom xexpr)
      xexpr
      (let ((op (first xexpr))
            (z (second xexpr))
            (y (third xexpr)))
        (let* ((f (simplify-no-redundant-checks z))
               (g (simplify-no-redundant-checks y))
               (nf (numberp f))
               (ng (numberp g)))
          (tagbody
           START
             (if (eq '+ op) (go OPTIMIZE-PLUS) (go TEST-MULTIPLY))
           OPTIMIZE-PLUS
             (when (and nf ng) (return-from simplify-no-redundant-
checks (+
f g)))
           TEST-PLUS-ZEROS
             (when (eql f 0) (return-from simplify-no-redundant-checks
g))
             (when (eql g 0) (return-from simplify-no-redundant-checks
f))
             (go REARRANGE-EXPR)
           TEST-MULTIPLY
             (unless (eq '* op) (go REARRANGE-EXPR))
           OPTIMIZE-MULTIPLY
             (when (and nf ng) (return-from simplify-no-redundant-
checks (*
f g)))
           TEST-MULTIPLY-ZEROS-AND-ONES
             (when (or (eql f 0) (eql g 0)) (return-from
simplify-no-redundant-checks 0))
             (when (eql f 1) (return-from simplify-no-redundant-checks
g))
             (when (eql g 1) (return-from simplify-no-redundant-checks
f))
           REARRANGE-EXPR
             (when (and (listp g) (eq op (first g)))
               (let ((op2 (first g))
                     (u (second g))
                     (v (third g)))
                 (declare (ignore op2))
                 (return-from simplify-no-redundant-checks
                   (simplify-no-redundant-checks (list op (list op f
u)
v)))))
           MAYBE-CONS-EXPR
             (if (and (eq f z) (eq g y))
                 (return-from simplify-no-redundant-checks xexpr)
                 (return-from simplify-no-redundant-checks (list op f
g))))))))

********************************************************************
Language: Lisp
Author: Pascal Constanza
Length: 27 lines

(defstruct add x y)
(defstruct mul x y)

(defgeneric simplify-add (x y)
  (declare (optimize (speed 3)))
   (:method ((x number) (y number)) (+ x y))
   (:method ((x (eql 0)) y) y)
   (:method (x (y (eql 0))) x)
   (:method (x (y add))
    (simplify-add (simplify-add x (add-x y)) (add-y y)))
   (:method (x y) (make-add :x x :y y)))

(defgeneric simplify-mul (x y)
  (declare (optimize (speed 3)))
   (:method ((x number) (y number)) (* x y))
   (:method ((x (eql 0)) y) 0)
   (:method (x (y (eql 0))) 0)
   (:method ((x (eql 1)) y) y)
   (:method (x (y (eql 1))) x)
   (:method (x (y mul))
    (simplify-mul (simplify-mul x (mul-x y)) (mul-y y)))
   (:method (x y) (make-mul :x x :y y)))

(defgeneric simplify (exp)
  (declare (optimize (speed 3)))
   (:method (exp) exp)
   (:method ((exp add))
    (simplify-add (simplify (add-x exp)) (simplify (add-y exp))))
   (:method ((exp mul))
    (simplify-mul (simplify (mul-x exp)) (simplify (mul-y exp)))))

The Results
------------------

All Qi/Lisp programs were running under Windows SBCL 1.0. The platform
was a 2.6 GHz Intel PC with 500 Mb of main memory.  The challenge was
to simplify [* x [+ [+ [* 12 0] [+ 23 8]] y]].
10^6 iterations were used as the benchmark.

Qi 8.0     Qi Turbo-E	Nathan	Andre	Pascal	Jon
*******************************************************************
0.9s	0.625s	0.49s 	1.59s	0.09s	?

Evaluation
-----------------

Missing is Jon Harrop's OCaml version.  I'm not into OCaml enough to
know how to run and time this program.

====> Any takers out there to fill in the gap?

Jon says himself that

'....Lisp's fastest time is only 3x slower than the OCaml (using
Nathan's hand-optimised pattern match)'

However Nathan's hand-optimised pattern match is not the fastest
version.  That honour goes to Pascal's version which seems to be on a
par with OCaml taking Jon's assessment as correct.  However
elsewhere Jon says

'The fastest Lisp implementation to date was written by Pascal
Constanza. It is also quite elegant but still 3x slower than the
OCaml. More interestingly, it avoids s-exprs:...'

Perhaps a slip of the pen here.  Perhaps he meant that OCaml is 3X
faster than Pascal's program.

Addendum: The Qi program under Turbo-E compiles into 119 lines of Lisp

(DEFUN simplify (V154)
  (BLOCK NIL
    (TAGBODY
      (IF (CONSP V154)
          (LET ((Cdr464 (CDR V154)))
            (IF (CONSP Cdr464)
                (LET ((Cdr463 (CDR Cdr464)))
                  (IF (CONSP Cdr463)
                      (IF (NULL (CDR Cdr463))
                          (RETURN
                           (s
                            (LIST (CAR V154) (simplify (CAR Cdr464))
                                  (simplify (CAR Cdr463)))))
                          (GO tag459))
                      (GO tag459)))
                (GO tag459))))
     tag459
      (RETURN V154))))

(DEFUN s (V155)
  (BLOCK NIL
    (TAGBODY
      (IF (CONSP V155)
          (LET ((Car514 (CAR V155)) (Cdr515 (CDR V155)))
            (TAGBODY
              (IF (EQ '+ Car514)
                  (IF (CONSP Cdr515)
                      (LET ((Car488 (CAR Cdr515)) (Cdr489 (CDR
Cdr515)))
                        (TAGBODY
                          (IF (CONSP Cdr489)
                              (LET ((Car487 (CAR Cdr489)))
                                (IF (NULL (CDR Cdr489))
                                    (IF (AND (NUMBERP Car488) (NUMBERP
Car487))
                                        (RETURN (THE NUMBER (+ Car488
Car487)))
                                        (GO tag468))
                                    (GO tag468))))
                         tag468
                          (TAGBODY
                            (IF (EQL 0 Car488)
                                (IF (CONSP Cdr489)
                                    (IF (NULL (CDR Cdr489))
                                        (RETURN (CAR Cdr489)) (GO
tag471))
                                    (GO tag471)))
                           tag471
                            (IF (CONSP Cdr489)
                                (LET ((Car485 (CAR Cdr489))
                                      (Cdr486 (CDR Cdr489)))
                                  (TAGBODY
                                    (IF (EQL 0 Car485)
                                        (IF (NULL Cdr486) (RETURN
Car488)
                                            (GO tag475)))
                                   tag475
                                    (IF (CONSP Car485)
                                        (LET ((Cdr484 (CDR Car485)))
                                          (IF (EQ '+ (CAR Car485))
                                              (IF (CONSP Cdr484)
                                                  (LET ((Cdr483 (CDR
Cdr484)))
                                                    (IF (CONSP Cdr483)
                                                        (IF (NULL (CDR
Cdr483))
                                                            (IF (NULL
Cdr486)
 
(RETURN
                                                                 (CONS
'+
 
(CONS
 
(LIST
 
'+
 
Car488
 
(CAR
 
Cdr484
))
 
Cdr483))
)
                                                                (GO
tag466))
                                                            (GO
tag466))
                                                        (GO tag466)))
                                                  (GO tag466))
                                              (GO tag466)))
                                        (GO tag466))))
                                (GO tag466)))))
                      (GO tag466)))
             tag466
              (IF (EQ '* Car514)
                  (IF (CONSP Cdr515)
                      (LET ((Car512 (CAR Cdr515)) (Cdr513 (CDR
Cdr515)))
                        (TAGBODY
                          (IF (CONSP Cdr513)
                              (LET ((Car511 (CAR Cdr513)))
                                (IF (NULL (CDR Cdr513))
                                    (IF (AND (NUMBERP Car512) (NUMBERP
Car511))
                                        (RETURN (THE NUMBER (* Car512
Car511)))
                                        (GO tag492))
                                    (GO tag492))))
                         tag492
                          (TAGBODY
                            (IF (EQL 0 Car512)
                                (IF (CONSP Cdr513)
                                    (IF (NULL (CDR Cdr513)) (RETURN 0)
                                        (GO tag495))
                                    (GO tag495)))
                           tag495
                            (IF (CONSP Cdr513)
                                (LET ((Car509 (CAR Cdr513))
                                      (Cdr510 (CDR Cdr513)))
                                  (TAGBODY
                                    (IF (EQL 0 Car509)
                                        (IF (NULL Cdr510) (RETURN 0)
                                            (GO tag499)))
                                   tag499
                                    (IF (CONSP Car509)
                                        (LET ((Cdr508 (CDR Car509)))
                                          (IF (EQ '* (CAR Car509))
                                              (IF (CONSP Cdr508)
                                                  (LET ((Cdr507 (CDR
Cdr508)))
                                                    (IF (CONSP Cdr507)
                                                        (IF (NULL (CDR
Cdr507))
                                                            (IF (NULL
Cdr510)
 
(RETURN
                                                                 (CONS
 
(LIST Car512
 
'*
 
(CAR
 
Cdr508)
)
 
(CONS '*
 
Cdr507))
)
                                                                (GO
tag465))
                                                            (GO
tag465))
                                                        (GO tag465)))
                                                  (GO tag465))
                                              (GO tag465)))
                                        (GO tag465))))
                                (GO tag465)))))
                      (GO tag465))
                  (GO tag465)))))
     tag465
      (RETURN V155))))

Mark

From: Dan Bensen
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <f6vsu8$81l$1@wildfire.prairienet.org>
Mark Tarver wrote:
> The Solutions
> **************************************
> Language: Lisp
> Author: Andre Thieme
> Author: Nathan Froyd
> Author: Pascal Constanza

I submitted another solution last week:
http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/e69f2854fe5d19b5/305dbf8ead8fdd39?lnk=gst&q=%22Okay%2C+here%27s+an+entry%22&rnum=1#305dbf8ead8fdd39

(defmacro defop (func op ident zero-case)
   (let ((e1 (gensym "E1"))
         (e2 (gensym "E2")))
    `(defun ,func (,e1 ,e2)
      ,(delete :no-case
        `(case ,e1
          ,zero-case
          (,ident ,e2)
          (t ,(delete :no-case
            `(case ,e2
             ,zero-case
             (,ident ,e1)
             (t (if (atom ,e2) (list ,e1 ,op ,e2)
               (case (cadr ,e2)
                (,op (,func (,func ,e1 (car ,e2)) (caddr ,e2)))
                (t  (list ,e1 ,op ,e2)))))))))))))

(defop expr+ '+ 0 :no-case)
(defop expr* '* 1 ( 0  0 ))

(defun simplify (expr)
   (if (atom expr)
      expr
    (let ((e1 (simplify (car   expr)))
          (e2 (simplify (caddr expr))))
     (case (cadr expr)
           ('+ (expr+ e1 e2))
           ('* (expr* e1 e2))))))

-- 
Dan
www.prairienet.org/~dsb/
From: Mark Tarver
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <1184077242.035515.181730@o61g2000hsh.googlegroups.com>
On 10 Jul, 13:15, Dan Bensen <··········@cyberspace.net> wrote:
> Mark Tarver wrote:
> > The Solutions
> > **************************************
> > Language: Lisp
> > Author: Andre Thieme
> > Author: Nathan Froyd
> > Author: Pascal Constanza
>
> I submitted another solution last week:http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/e6...
>
> (defmacro defop (func op ident zero-case)
>    (let ((e1 (gensym "E1"))
>          (e2 (gensym "E2")))
>     `(defun ,func (,e1 ,e2)
>       ,(delete :no-case
>         `(case ,e1
>           ,zero-case
>           (,ident ,e2)
>           (t ,(delete :no-case
>             `(case ,e2
>              ,zero-case
>              (,ident ,e1)
>              (t (if (atom ,e2) (list ,e1 ,op ,e2)
>                (case (cadr ,e2)
>                 (,op (,func (,func ,e1 (car ,e2)) (caddr ,e2)))
>                 (t  (list ,e1 ,op ,e2)))))))))))))
>
> (defop expr+ '+ 0 :no-case)
> (defop expr* '* 1 ( 0  0 ))
>
> (defun simplify (expr)
>    (if (atom expr)
>       expr
>     (let ((e1 (simplify (car   expr)))
>           (e2 (simplify (caddr expr))))
>      (case (cadr expr)
>            ('+ (expr+ e1 e2))
>            ('* (expr* e1 e2))))))
>
> --
> Danwww.prairienet.org/~dsb/

Equal with Pascal I should say

Revised Results are

           SBCL 1.0 Windows, 2.6GHz, 500Mb RAM
                           |
       -------------------------------------------------
      |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
*******************************************************************
time   0.9s    0.625s       0.49s   1.59s   0.09s   0.93s   ?

Mark
loc    15      15           42      23      27      26      15
From: Mark Tarver
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <1184077591.410616.88030@q75g2000hsh.googlegroups.com>
On 10 Jul, 15:20, Mark Tarver <··········@ukonline.co.uk> wrote:
> On 10 Jul, 13:15, Dan Bensen <··········@cyberspace.net> wrote:
>
>
>
>
>
> > Mark Tarver wrote:
> > > The Solutions
> > > **************************************
> > > Language: Lisp
> > > Author: Andre Thieme
> > > Author: Nathan Froyd
> > > Author: Pascal Constanza
>
> > I submitted another solution last week:http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/e6...
>
> > (defmacro defop (func op ident zero-case)
> >    (let ((e1 (gensym "E1"))
> >          (e2 (gensym "E2")))
> >     `(defun ,func (,e1 ,e2)
> >       ,(delete :no-case
> >         `(case ,e1
> >           ,zero-case
> >           (,ident ,e2)
> >           (t ,(delete :no-case
> >             `(case ,e2
> >              ,zero-case
> >              (,ident ,e1)
> >              (t (if (atom ,e2) (list ,e1 ,op ,e2)
> >                (case (cadr ,e2)
> >                 (,op (,func (,func ,e1 (car ,e2)) (caddr ,e2)))
> >                 (t  (list ,e1 ,op ,e2)))))))))))))
>
> > (defop expr+ '+ 0 :no-case)
> > (defop expr* '* 1 ( 0  0 ))
>
> > (defun simplify (expr)
> >    (if (atom expr)
> >       expr
> >     (let ((e1 (simplify (car   expr)))
> >           (e2 (simplify (caddr expr))))
> >      (case (cadr expr)
> >            ('+ (expr+ e1 e2))
> >            ('* (expr* e1 e2))))))
>
> > --
> > Danwww.prairienet.org/~dsb/
>
> Equal with Pascal I should say
>
> Revised Results are
>
>            SBCL 1.0 Windows, 2.6GHz, 500Mb RAM
>                            |
>        -------------------------------------------------
>       |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
> *******************************************************************
> time   0.9s    0.625s       0.49s   1.59s   0.09s   0.93s   ?
>
> Mark
> loc    15      15           42      23      27      26      15- Hide quoted text -
>
> - Show quoted text -

Sorry Dan,

I missed the decimal place - its 0.093 not 0.93s. Of course.

Comes from not getting enough sleep!

Mark

           SBCL 1.0 Windows, 2.6GHz, 500Mb RAM
                           |
       -------------------------------------------------
      |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
*******************************************************************
time   0.9s    0.625s       0.49s   1.59s   0.09s   0.093s   ?
loc    15      15           42      23      27      26      15
From: Mark Tarver
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml (revised)
Date: 
Message-ID: <1184084439.245899.108870@k79g2000hse.googlegroups.com>
On 10 Jul, 15:26, Mark Tarver <··········@ukonline.co.uk> wrote:
> On 10 Jul, 15:20, Mark Tarver <··········@ukonline.co.uk> wrote:
>
>
>
>
>
> > On 10 Jul, 13:15, Dan Bensen <··········@cyberspace.net> wrote:
>
> > > Mark Tarver wrote:
> > > > The Solutions
> > > > **************************************
> > > > Language: Lisp
> > > > Author: Andre Thieme
> > > > Author: Nathan Froyd
> > > > Author: Pascal Constanza
>
> > > I submitted another solution last week:http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/e6...
>
> > > (defmacro defop (func op ident zero-case)
> > >    (let ((e1 (gensym "E1"))
> > >          (e2 (gensym "E2")))
> > >     `(defun ,func (,e1 ,e2)
> > >       ,(delete :no-case
> > >         `(case ,e1
> > >           ,zero-case
> > >           (,ident ,e2)
> > >           (t ,(delete :no-case
> > >             `(case ,e2
> > >              ,zero-case
> > >              (,ident ,e1)
> > >              (t (if (atom ,e2) (list ,e1 ,op ,e2)
> > >                (case (cadr ,e2)
> > >                 (,op (,func (,func ,e1 (car ,e2)) (caddr ,e2)))
> > >                 (t  (list ,e1 ,op ,e2)))))))))))))
>
> > > (defop expr+ '+ 0 :no-case)
> > > (defop expr* '* 1 ( 0  0 ))
>
> > > (defun simplify (expr)
> > >    (if (atom expr)
> > >       expr
> > >     (let ((e1 (simplify (car   expr)))
> > >           (e2 (simplify (caddr expr))))
> > >      (case (cadr expr)
> > >            ('+ (expr+ e1 e2))
> > >            ('* (expr* e1 e2))))))
>
> > > --
> > > Danwww.prairienet.org/~dsb/
>
> > Equal with Pascal I should say
>
> > Revised Results are
>
> >            SBCL 1.0 Windows, 2.6GHz, 500Mb RAM
> >                            |
> >        -------------------------------------------------
> >       |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
> > *******************************************************************
> > time   0.9s    0.625s       0.49s   1.59s   0.09s   0.93s   ?
>
> > Mark
> > loc    15      15           42      23      27      26      15- Hide quoted text -
>
> > - Show quoted text -
>
> Sorry Dan,
>
> I missed the decimal place - its 0.093 not 0.93s. Of course.
>
> Comes from not getting enough sleep!
>
> Mark
>
>            SBCL 1.0 Windows, 2.6GHz, 500Mb RAM
>                            |
>        -------------------------------------------------
>       |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
> *******************************************************************
> time   0.9s    0.625s       0.49s   1.59s   0.09s   0.093s   ?
> loc    15      15           42      23      27      26      15- Hide quoted text -
>
> - Show quoted text -

Actually - a faster version in Qi of equal length to the original is

(define simplify
  [Op A B] -> (s Op (simplify A) (simplify B))
  A -> A)

(define s
  + M N -> (+ M N)	   where (and (number? M) (number? N))
  + 0 F -> F
  + F 0 -> F
  + A [+ B C] -> [+ [+ A B] C]
  * M N -> (* M N)	 where (and (number? M) (number? N))
  * 0 F -> 0
  * F 0 -> 0
  * F 1 -> F
  * 1 F -> F
  * A [* B C] -> [* [* A B] C]
  Op A B -> [Op A B])

we then get

                 SBCL 1.0 Windows, 2.6GHz, 500Mb RAM
                           |
       -------------------------------------------------
      |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
*******************************************************************
time   0.56s    0.38s       0.49s   1.59s   0.09s   0.093s   ?
loc    15      15           42      23      27      26      15
From: Marcus Breiing
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <f70pgh$jpp$1@chessie.cirr.com>
Mark Tarver <··········@ukonline.co.uk> writes:

> 
>            SBCL 1.0 Windows, 2.6GHz, 500Mb RAM
>                            |
>        -------------------------------------------------
>       |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
> *******************************************************************
> time   0.9s    0.625s       0.49s   1.59s   0.09s   0.093s   ?
> loc    15      15           42      23      27      26      15

I tried to reproduce your (non-Qi) results, but got some significant
differences. I think your timings for "Pascal" and "Dan" may be off by
large factors due to wrong inputs.

"Pascal" doesn't take a prefix-sexp expression, but one made up of
structs. A correct invocation for the challenge problem should look
like this.

  (simplify-pascal
   (make-mul :x 'x
             :y (make-add :x (make-add :x (make-mul :x 12 :y 0)
                                       :y (make-add :x 23 :y 8))
                          :y 'y)))


"Dan" takes infix-sexp input, and should be invoked like this:

  (simplify-dan '(x * (((12 * 0) + (23 + 8)) + y)))

BTW, "Dan" returns (X * ((23 + 8) + Y)), seemingly missing out on a
simplification.

With these inputs, on a slightly slower machine and using CMU 19c, I
get:

Nathan 0.96
Andre  1.25
Pascal 3.41
Dan    1.19

I don't have Qi installed. My own (unpublished) pattern matcher gives
results virtually indistinguishable from "Nathan". It was explicitly
written to avoid redundant tests, which probably explains the
similarity. It looks like this:

(defun simplify (exp)
  (labels ((s+ (x y)
             (mcase (values x y)
               ((values (the number _) (the number _)) (+ x y))
               ((values 0 _) y)
               ((values _ 0) x)
               ((values _ `(+ ,a ,b)) (s+ (s+ x a) b))
               ((values _ _) `(+ ,x ,y))))
           (s* (x y)
             (mcase (values x y)
               ((values (the number _) (the number _)) (* x y))
               ((values 0 _) 0)
               ((values _ 0) 0)
               ((values 1 _) y)
               ((values _ 1) x)
               ((values _ `(* ,a ,b)) (s* (s* x a) b))
               ((values _ _) `(* ,x ,y)))))
    (mcase exp
      (`(+ ,x ,y) (s+ (simplify x) (simplify y)))
      (`(* ,x ,y) (s* (simplify x) (simplify y)))
      (_ exp))))

-- 
Marcus Breiing
(Cologne, Germany)
From: Mark Tarver
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <1184102425.584592.308760@w3g2000hsg.googlegroups.com>
On 10 Jul, 21:16, Marcus Breiing <······@2007w27.mail.breiing.com>
wrote:
> Mark Tarver <··········@ukonline.co.uk> writes:
>
> >            SBCL 1.0 Windows, 2.6GHz, 500Mb RAM
> >                            |
> >        -------------------------------------------------
> >       |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
> > *******************************************************************
> > time   0.9s    0.625s       0.49s   1.59s   0.09s   0.093s   ?
> > loc    15      15           42      23      27      26      15
>
> I tried to reproduce your (non-Qi) results, but got some significant
> differences. I think your timings for "Pascal" and "Dan" may be off by
> large factors due to wrong inputs.
>
> "Pascal" doesn't take a prefix-sexp expression, but one made up of
> structs. A correct invocation for the challenge problem should look
> like this.
>
>   (simplify-pascal
>    (make-mul :x 'x
>              :y (make-add :x (make-add :x (make-mul :x 12 :y 0)
>                                        :y (make-add :x 23 :y 8))
>                           :y 'y)))
>
> "Dan" takes infix-sexp input, and should be invoked like this:
>
>   (simplify-dan '(x * (((12 * 0) + (23 + 8)) + y)))
>
> BTW, "Dan" returns (X * ((23 + 8) + Y)), seemingly missing out on a
> simplification.
>
> With these inputs, on a slightly slower machine and using CMU 19c, I
> get:
>
> Nathan 0.96
> Andre  1.25
> Pascal 3.41
> Dan    1.19
>
> I don't have Qi installed. My own (unpublished) pattern matcher gives
> results virtually indistinguishable from "Nathan". It was explicitly
> written to avoid redundant tests, which probably explains the
> similarity. It looks like this:
>
> (defun simplify (exp)
>   (labels ((s+ (x y)
>              (mcase (values x y)
>                ((values (the number _) (the number _)) (+ x y))
>                ((values 0 _) y)
>                ((values _ 0) x)
>                ((values _ `(+ ,a ,b)) (s+ (s+ x a) b))
>                ((values _ _) `(+ ,x ,y))))
>            (s* (x y)
>              (mcase (values x y)
>                ((values (the number _) (the number _)) (* x y))
>                ((values 0 _) 0)
>                ((values _ 0) 0)
>                ((values 1 _) y)
>                ((values _ 1) x)
>                ((values _ `(* ,a ,b)) (s* (s* x a) b))
>                ((values _ _) `(* ,x ,y)))))
>     (mcase exp
>       (`(+ ,x ,y) (s+ (simplify x) (simplify y)))
>       (`(* ,x ,y) (s* (simplify x) (simplify y)))
>       (_ exp))))
>
> --
> Marcus Breiing
> (Cologne, Germany)

Yes, you're right!  I pasted the same test into his file that
I had used on Nathan and Andre. Thanks for that, Marcus.

Dan is adhering to the terms of the original spec in using infix.
I'll ask him to fix his bug if he would so I can get a fair timing.

Ok, see if we can get this right.

I've run this again using the proper inputs; on my machine we get.

             SBCL 1.0 Windows, 2.6GHz, 500Mb RAM
                            |
        -------------------------------------------------
       |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
 *******************************************************************
 time   0.56s   0.38s       0.49s   1.59s   0.95s   0.47s   ?
 loc    15      15           42      23      27      26      15

Hum - the unreleased Turbo-E is top* ;) Well its not a fix - honest!

Mark

* Its top until perhaps O'Caml does its stuff.
From: Dan Bensen
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <f7135r$k9f$1@wildfire.prairienet.org>
Mark Tarver wrote:
> Dan is adhering to the terms of the original spec in using infix.
> I'll ask him to fix his bug if he would so I can get a fair timing.

(defmacro defop (func op op-symbl ident zero-case)
   (let ((e1 (gensym "E1"))
         (e2 (gensym "E2")))
     `(defun ,func (,e1 ,e2)
       (declare (optimize (speed 3)))
        ,(delete :no-case
          `(case ,e1
            ,zero-case
            (,ident ,e2)
            (t ,(delete :no-case
               `(case ,e2
                ,zero-case
                (,ident ,e1)
                (t (cond
                   ((and (rationalp ,e1)
                         (rationalp ,e2))
                    (,op ,e1 ,e2))
                   ((atom ,e2)
                    (list ,e1 ,op-symbl ,e2))
                   (t (case
                        (cadr ,e2)
                      (,op-symbl (,func (,func ,e1 (car ,e2))
                                        (caddr ,e2)))
                      (t  (list ,e1 ,op-symbl ,e2))))))))))))))

(defop apply+ + '+ 0 :no-case)
(defop apply* * '* 1 ( 0  0 ))

(defun simplify (expr)
   (if (atom expr)
       expr
     (let ((e1 (simplify (car   expr)))
           (e2 (simplify (caddr expr))))
       (case (cadr expr)
             ('+ (apply+ e1 e2))
             ('* (apply* e1 e2))))))

-- 
Dan
www.prairienet.org/~dsb/
From: Mark Tarver
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <1184110960.361455.225730@w3g2000hsg.googlegroups.com>
On 11 Jul, 00:08, Dan Bensen <··········@cyberspace.net> wrote:
> Mark Tarver wrote:
> > Dan is adhering to the terms of the original spec in using infix.
> > I'll ask him to fix his bug if he would so I can get a fair timing.
>
> (defmacro defop (func op op-symbl ident zero-case)
>    (let ((e1 (gensym "E1"))
>          (e2 (gensym "E2")))
>      `(defun ,func (,e1 ,e2)
>        (declare (optimize (speed 3)))
>         ,(delete :no-case
>           `(case ,e1
>             ,zero-case
>             (,ident ,e2)
>             (t ,(delete :no-case
>                `(case ,e2
>                 ,zero-case
>                 (,ident ,e1)
>                 (t (cond
>                    ((and (rationalp ,e1)
>                          (rationalp ,e2))
>                     (,op ,e1 ,e2))
>                    ((atom ,e2)
>                     (list ,e1 ,op-symbl ,e2))
>                    (t (case
>                         (cadr ,e2)
>                       (,op-symbl (,func (,func ,e1 (car ,e2))
>                                         (caddr ,e2)))
>                       (t  (list ,e1 ,op-symbl ,e2))))))))))))))
>
> (defop apply+ + '+ 0 :no-case)
> (defop apply* * '* 1 ( 0  0 ))
>
> (defun simplify (expr)
>    (if (atom expr)
>        expr
>      (let ((e1 (simplify (car   expr)))
>            (e2 (simplify (caddr expr))))
>        (case (cadr expr)
>              ('+ (apply+ e1 e2))
>              ('* (apply* e1 e2))))))
>
> --
> Danwww.prairienet.org/~dsb/

Thanks for that one; we have now

           SBCL 1.0 Windows, 2.6GHz, 500Mb RAM
                            |
       -------------------------------------------------
       |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
 *******************************************************************
 time   0.56s   0.38s       0.49s   1.59s   0.95s   0.53s    ?
 loc    15      15           42      23      27      26      15

One camel to go.

Mark
From: Paul Rubin
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <7xfy3vkeie.fsf@ruckus.brouhaha.com>
Mark Tarver <··········@ukonline.co.uk> writes:
>        |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
>  *******************************************************************
>  time   0.56s   0.38s       0.49s   1.59s   0.95s   0.53s    ?
>  loc    15      15           42      23      27      26      15
> 
> One camel to go.

Can someone code a GHC version?
From: Ben Bacarisse
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <877ip4vy8b.fsf@bsb.me.uk>
Paul Rubin <·············@NOSPAM.invalid> writes:

> Mark Tarver <··········@ukonline.co.uk> writes:
>>        |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
>>  *******************************************************************
>>  time   0.56s   0.38s       0.49s   1.59s   0.95s   0.53s    ?
>>  loc    15      15           42      23      27      26      15
>> 
>> One camel to go.
>
> Can someone code a GHC version?

Too late?  BTW I am a Haskell novice, so the implementation is basic.
I can't compile any of the other versions so I can only report that is
takes about 0.40s on my laptop (Intel(R) Pentium(R) M processor
2.00GHz, GHC 6.6).

{- CODE START -}

data Expression
    = I Integer
    | S String
    | Add Expression Expression
    | Mul Expression Expression
      deriving Show

simplify :: Expression -> Expression
simplify e =
    case e of
      (Add a b) -> simp (Add (simplify a) (simplify b))
      (Mul a b) -> simp (Mul (simplify a) (simplify b))
      e -> e
    where
      simp :: Expression -> Expression
      simp (Add (I x) (I y)) = I (x + y)
      simp (Add (I 0) e) = e
      simp (Add e (I 0)) = e
      simp (Mul (I x) (I y)) = I (x * y)
      simp (Mul (I 0) _) = I 0
      simp (Mul _ (I 0)) = I 0
      simp (Mul (I 1) e) = e
      simp (Mul e (I 1)) = e
      simp (Mul a (Mul b c)) = (Mul (Mul a b) c)
      simp (Add a (Add b c)) = (Add (Add a b) c)
      simp e = e

-- [* x [+ [+ [* 12 0] [+ 23 8]] y]].
test = (Mul (S "x") (Add (Add (Mul (I 12) (I 0)) (Add (I 23) (I 8))) (S "y")))

main :: IO ()
main = putStrLn $ show $ last $ map simplify (replicate (10^7) test)

{- CODE END -}

Obviously, a compiler could optimise that repetition away, but GHC
leaves it (at least the execution time scales with the number in the
replicate call!).

-- 
Ben.
From: David Golden
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <XgVki.20802$j7.378365@news.indigo.ie>
Does Qi stick in declarations similar to the embedded declarations in
the lisp examples for the underlying lisp compiler?  I dunno
if it has much effect on this particular code, but that "(declare
(optimise (speed 3)))" can make a difference in some lisps for some
applications.
From: Mark Tarver
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <1184141729.565002.250560@n2g2000hse.googlegroups.com>
On 11 Jul, 01:13, David Golden <············@oceanfree.net> wrote:
> Does Qi stick in declarations similar to the embedded declarations in
> the lisp examples for the underlying lisp compiler?  I dunno
> if it has much effect on this particular code, but that "(declare
> (optimise (speed 3)))" can make a difference in some lisps for some
> applications.

Qi does put in type declarations based on its type inferencing.  You
can associate a Qi type with a Lisp type too.  But here there's not
much of that going on - the type checker is off.

All the code being run save Dan's had (optimize (speed 3)) in it.
Qi runs under this default setting.  But now you mentioned it I put
this into Dan's code and ran it again.  It made no discernable
difference.

Mark
From: Dan Bensen
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <f72i5h$3hp$1@wildfire.prairienet.org>
Mark Tarver wrote:
> All the code being run save Dan's had (optimize (speed 3)) in it.
> Qi runs under this default setting.  But now you mentioned it I put
> this into Dan's code and ran it again.  It made no discernable
> difference.

You mean you added it to simplify?  I put it into the last version of
apply? (? = +|*).  Maybe try taking it out of the definition in defop.
That's what does most of the work.

-- 
Dan
www.prairienet.org/~dsb/
From: David Golden
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <RN3li.20809$j7.378129@news.indigo.ie>
Mark Tarver wrote:
> 
> Qi does put in type declarations based on its type inferencing.  You
> can associate a Qi type with a Lisp type too.  But here there's not
> much of that going on - the type checker is off.
> 

And do you get faster results with the type checker on?
(given that SBCL may need some declarations for its own
checking and inferencing).
From: Mark Tarver
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <1184160807.350174.62220@w3g2000hsg.googlegroups.com>
On 11 Jul, 13:11, David Golden <············@oceanfree.net> wrote:
> Mark Tarver wrote:
>
> > Qi does put in type declarations based on its type inferencing.  You
> > can associate a Qi type with a Lisp type too.  But here there's not
> > much of that going on - the type checker is off.
>
> And do you get faster results with the type checker on?
> (given that SBCL may need some declarations for its own
> checking and inferencing).

Probably not; there's not much to optimise type theory wise in this
program.

Mark
From: Dimiter "malkia" Stanev
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <46969AA7.8080504@mac.com>
Under lispworks, I found out that (optimize (speed 3)) is not enough,
I'm using (optimize (speed 3) (safety 0) (debug 0) (space 0) 
(compilation-speed 0)). Off course all this could be declaim'd

and in case of fixnums only arithmetic, I'm also doing this:

(optimize #+lispworks (fixnum-safety 0))

if it's float point only:

(optimize #+lispworks (float 0))

Probably the other implementations would have similiar options.

I've found that having (debug) set to anything above 0, would create 
additional code (disassemblin'g it).

Then again, I needed that just for some really tight decompression code, 
just to get feel of lispworks optimizer. It's not the smartest compiler, 
  but still gives good results.

Mark Tarver wrote:
> On 11 Jul, 01:13, David Golden <············@oceanfree.net> wrote:
>> Does Qi stick in declarations similar to the embedded declarations in
>> the lisp examples for the underlying lisp compiler?  I dunno
>> if it has much effect on this particular code, but that "(declare
>> (optimise (speed 3)))" can make a difference in some lisps for some
>> applications.
> 
> Qi does put in type declarations based on its type inferencing.  You
> can associate a Qi type with a Lisp type too.  But here there's not
> much of that going on - the type checker is off.
> 
> All the code being run save Dan's had (optimize (speed 3)) in it.
> Qi runs under this default setting.  But now you mentioned it I put
> this into Dan's code and ran it again.  It made no discernable
> difference.
> 
> Mark
> 
From: Mark Tarver
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <1184103918.941644.205550@57g2000hsv.googlegroups.com>
On 10 Jul, 21:16, Marcus Breiing <······@2007w27.mail.breiing.com>
wrote:
> Mark Tarver <··········@ukonline.co.uk> writes:
>
> >            SBCL 1.0 Windows, 2.6GHz, 500Mb RAM
> >                            |
> >        -------------------------------------------------
> >       |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
> > *******************************************************************
> > time   0.9s    0.625s       0.49s   1.59s   0.09s   0.093s   ?
> > loc    15      15           42      23      27      26      15
>
> I tried to reproduce your (non-Qi) results, but got some significant
> differences. I think your timings for "Pascal" and "Dan" may be off by
> large factors due to wrong inputs.
>
> "Pascal" doesn't take a prefix-sexp expression, but one made up of
> structs. A correct invocation for the challenge problem should look
> like this.
>
>   (simplify-pascal
>    (make-mul :x 'x
>              :y (make-add :x (make-add :x (make-mul :x 12 :y 0)
>                                        :y (make-add :x 23 :y 8))
>                           :y 'y)))
>
> "Dan" takes infix-sexp input, and should be invoked like this:
>
>   (simplify-dan '(x * (((12 * 0) + (23 + 8)) + y)))
>
> BTW, "Dan" returns (X * ((23 + 8) + Y)), seemingly missing out on a
> simplification.
>
> With these inputs, on a slightly slower machine and using CMU 19c, I
> get:
>
> Nathan 0.96
> Andre  1.25
> Pascal 3.41
> Dan    1.19
>
> I don't have Qi installed. My own (unpublished) pattern matcher gives
> results virtually indistinguishable from "Nathan". It was explicitly
> written to avoid redundant tests, which probably explains the
> similarity. It looks like this:
>
> (defun simplify (exp)
>   (labels ((s+ (x y)
>              (mcase (values x y)
>                ((values (the number _) (the number _)) (+ x y))
>                ((values 0 _) y)
>                ((values _ 0) x)
>                ((values _ `(+ ,a ,b)) (s+ (s+ x a) b))
>                ((values _ _) `(+ ,x ,y))))
>            (s* (x y)
>              (mcase (values x y)
>                ((values (the number _) (the number _)) (* x y))
>                ((values 0 _) 0)
>                ((values _ 0) 0)
>                ((values 1 _) y)
>                ((values _ 1) x)
>                ((values _ `(* ,a ,b)) (s* (s* x a) b))
>                ((values _ _) `(* ,x ,y)))))
>     (mcase exp
>       (`(+ ,x ,y) (s+ (simplify x) (simplify y)))
>       (`(* ,x ,y) (s* (simplify x) (simplify y)))
>       (_ exp))))
>
> --
> Marcus Breiing
> (Cologne, Germany)

Yes, you're right!  I pasted the same test into his file that
I had used on Nathan and Andre. Thanks for that, Marcus.

Dan is adhering to the terms of the original spec in using infix.
I'll ask him to fix his bug if he would so I can get a fair timing.

Ok, see if we can get this right.

I've run this again using the proper inputs; on my machine we get.

             SBCL 1.0 Windows, 2.6GHz, 500Mb RAM
                            |
        -------------------------------------------------
       |Qi 8.0  Qi Turbo-E   Nathan  Andre   Pascal  Dan |  Jon
 *******************************************************************
 time   0.56s   0.38s       0.49s   1.59s   0.95s   0.47s   ?
 loc    15      15           42      23      27      26      15

Hum - the unreleased Turbo-E is top* ;) Well its not a fix - honest!

Mark

* Its top until perhaps O'Caml does its stuff.
From: Marcus Breiing
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <f70q7f$jpp$2@chessie.cirr.com>
Marcus Breiing <······@2007w27.mail.breiing.com> writes:
> 
> Nathan 0.96
> Andre  1.25
> Pascal 3.41
> Dan    1.19

Above runs have "Pascal" at a disadvantage by creating its input on
each invocation, whereas the others are fed (read-time) constants.
Correcting that, I get

Nathan 0.96
Andre  1.25
Pascal 2.05
Dan    1.19

-- 
Marcus Breiing
(Cologne, Germany)
From: Mark Tarver
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <1184063356.197523.277910@n60g2000hse.googlegroups.com>
On 10 Jul, 11:06, Mark Tarver <··········@ukonline.co.uk> wrote:
> This test was conducted to determine the relative efficiency of hand-
> coded Lisp, OCaml, Qi 8.0 and Qi Turbo-E using the benchmark challenge
> provided by Jon Harrop.  Dr Harrop also provided the
> Lisp source written by Andre Thieme, Nathan Forster and Pascal
> Constanza.
>
> Turbo-E is an unreleased version of Qi which factorises its pattern-
> matching.
>
> Jon Harrop Challenge Problem
> --------------------------------------------
>
> Posted by Dr Harrop
>
> http://groups.google.co.uk/group/comp.lang.lisp/browse_thread/thread/...
>
> The problem is to simplify symbolic expressions by applying the
> following rewrite rules from the leaves up:
>
> rational n + rational m -> rational(n + m)
> rational n * rational m -> rational(n * m)
> symbol x -> symbol x
> 0+f -> f
> f+0 -> f
> 0*f -> 0
> f*0 -> 0
> 1*f -> f
> f*1 -> f
> a+(b+c) -> (a+b)+c
> a*(b*c) -> (a*b)*c
>
> The Solutions
> --------------------
>
> Language: Qi
> Author: Mark Tarver
> Length: 13 lines
>
> (define simplify
>   [Op A B] -> (s [Op (simplify A) (simplify B)])
>   A -> A)
>
> (define s
>   [+ M N] -> (+ M N) where (and (number? M) (number? N))
>   [+ 0 F] -> F
>   [+ F 0] -> F
>   [+ A [+ B C]] -> [+ [+ A B] C]
>   [* M N] -> (* M N) where (and (number? M) (number? N))
>   [* 0 F] -> 0
>   [* F 0] -> 0
>   [* A [* B C]] -> [[A * B] * C]
>   A -> A)
>
> * Note I have used prefix notation for this problem though Dr Harrop's
> formulation uses infix. It does make a lot of difference to the
> timings. The Lisp solutions follow prefix and so I chose to make my
> program comparable.*
>
> *********************************************************
> Language: OCaml
> Author: Jon Harrop
> Length: 15 lines
>
> let rec ( +: ) f g = match f, g with
>   | `Int n, `Int m -> `Int (n +/ m)
>   | `Int (Int 0), e | e, `Int (Int 0) -> e
>   | f, `Add(g, h) -> f +: g +: h
>   | f, g -> `Add(f, g)
>
> let rec ( *: ) f g = match f, g with
>   | `Int n, `Int m -> `Int (n */ m)
>   | `Int (Int 0), e | e, `Int (Int 0) -> `Int (Int 0)
>   | `Int (Int 1), e | e, `Int (Int 1) -> e
>   | f, `Mul(g, h) -> f *: g *: h
>   | f, g -> `Mul(f, g)
>
> let rec simplify = function
>   | `Int _ | `Var _ as f -> f
>   | `Add (f, g) -> simplify f +: simplify g
>   | `Mul (f, g) -> simplify f *: simplify g
> ********************************************************************
> Language: Lisp
> Author: Andre Thieme
> Length: 23 lines
>
> (defun simplify (a)
>    (if (atom a)
>        a
>        (destructuring-bind (op x y) a
>         (let* ((f (simplify x))
>                (g (simplify y))
>                (nf (numberp f))
>                (ng (numberp g))
>                (+? (eq '+ op))
>                (*? (eq '* op)))
>           (cond
>             ((and +? nf ng)                   (+ f g))
>             ((and +? nf (zerop f))            g)
>             ((and +? ng (zerop g))            f)
>             ((and (listp g) (eq op (first g)))
>              (destructuring-bind (op2 u v) g
>                (simplify `(,op (,op ,f ,u) ,v))))
>             ((and *? nf ng)                   (* f g))
>             ((and *? (or (and nf (zerop f))
>                          (and ng (zerop g)))) 0)
>             ((and *? nf (= 1 f))              g)
>             ((and *? ng (= 1 g))              f)
>             (t                                `(,op ,f ,g)))))))
>
> ********************************************************************
> Language: Lisp
> Author: Nathan Froyd
> Length: 42 lines
>
> (defun simplify-no-redundant-checks (xexpr)
>   (declare (optimize (speed 3)))
>   (if (atom xexpr)
>       xexpr
>       (let ((op (first xexpr))
>             (z (second xexpr))
>             (y (third xexpr)))
>         (let* ((f (simplify-no-redundant-checks z))
>                (g (simplify-no-redundant-checks y))
>                (nf (numberp f))
>                (ng (numberp g)))
>           (tagbody
>            START
>              (if (eq '+ op) (go OPTIMIZE-PLUS) (go TEST-MULTIPLY))
>            OPTIMIZE-PLUS
>              (when (and nf ng) (return-from simplify-no-redundant-
> checks (+
> f g)))
>            TEST-PLUS-ZEROS
>              (when (eql f 0) (return-from simplify-no-redundant-checks
> g))
>              (when (eql g 0) (return-from simplify-no-redundant-checks
> f))
>              (go REARRANGE-EXPR)
>            TEST-MULTIPLY
>              (unless (eq '* op) (go REARRANGE-EXPR))
>            OPTIMIZE-MULTIPLY
>              (when (and nf ng) (return-from simplify-no-redundant-
> checks (*
> f g)))
>            TEST-MULTIPLY-ZEROS-AND-ONES
>              (when (or (eql f 0) (eql g 0)) (return-from
> simplify-no-redundant-checks 0))
>              (when (eql f 1) (return-from simplify-no-redundant-checks
> g))
>              (when (eql g 1) (return-from simplify-no-redundant-checks
> f))
>            REARRANGE-EXPR
>              (when (and (listp g) (eq op (first g)))
>                (let ((op2 (first g))
>                      (u (second g))
>                      (v (third g)))
>                  (declare (ignore op2))
>                  (return-from simplify-no-redundant-checks
>                    (simplify-no-redundant-checks (list op (list op f
> u)
> v)))))
>            MAYBE-CONS-EXPR
>              (if (and (eq f z) (eq g y))
>                  (return-from simplify-no-redundant-checks xexpr)
>                  (return-from simplify-no-redundant-checks (list op f
> g))))))))
>
> ********************************************************************
> Language: Lisp
> Author: Pascal Constanza
> Length: 27 lines
>
> (defstruct add x y)
> (defstruct mul x y)
>
> (defgeneric simplify-add (x y)
>   (declare (optimize (speed 3)))
>    (:method ((x number) (y number)) (+ x y))
>    (:method ((x (eql 0)) y) y)
>    (:method (x (y (eql 0))) x)
>    (:method (x (y add))
>     (simplify-add (simplify-add x (add-x y)) (add-y y)))
>    (:method (x y) (make-add :x x :y y)))
>
> (defgeneric simplify-mul (x y)
>   (declare (optimize (speed 3)))
>    (:method ((x number) (y number)) (* x y))
>    (:method ((x (eql 0)) y) 0)
>    (:method (x (y (eql 0))) 0)
>    (:method ((x (eql 1)) y) y)
>    (:method (x (y (eql 1))) x)
>    (:method (x (y mul))
>     (simplify-mul (simplify-mul x (mul-x y)) (mul-y y)))
>    (:method (x y) (make-mul :x x :y y)))
>
> (defgeneric simplify (exp)
>   (declare (optimize (speed 3)))
>    (:method (exp) exp)
>    (:method ((exp add))
>     (simplify-add (simplify (add-x exp)) (simplify (add-y exp))))
>    (:method ((exp mul))
>     (simplify-mul (simplify (mul-x exp)) (simplify (mul-y exp)))))
>
> The Results
> ------------------
>
> All Qi/Lisp programs were running under Windows SBCL 1.0. The platform
> was a 2.6 GHz Intel PC with 500 Mb of main memory.  The challenge was
> to simplify [* x [+ [+ [* 12 0] [+ 23 8]] y]].
> 10^6 iterations were used as the benchmark.
>
> Qi 8.0     Qi Turbo-E   Nathan  Andre   Pascal  Jon
> *******************************************************************
> 0.9s    0.625s  0.49s   1.59s   0.09s   ?
>
> Evaluation
> -----------------
>
> Missing is Jon Harrop's OCaml version.  I'm not into OCaml enough to
> know how to run and time this program.
>
> ====> Any takers out there to fill in the gap?
>
> Jon says himself that
>
> '....Lisp's fastest time is only 3x slower than the OCaml (using
> Nathan's hand-optimised pattern match)'
>
> However Nathan's hand-optimised pattern match is not the fastest
> version.  That honour goes to Pascal's version which seems to be on a
> par with OCaml taking Jon's assessment as correct.  However
> elsewhere Jon says
>
> 'The fastest Lisp implementation to date was written by Pascal
> Constanza. It is also quite elegant but still 3x slower than the
> OCaml. More interestingly, it avoids s-exprs:...'
>
> Perhaps a slip of the pen here.  Perhaps he meant that OCaml is 3X
> faster than Pascal's program.
>
> Addendum: The Qi program under Turbo-E compiles into 119 lines of Lisp
>
> (DEFUN simplify (V154)
>   (BLOCK NIL
>     (TAGBODY
>       (IF (CONSP V154)
>           (LET ((Cdr464 (CDR V154)))
>             (IF (CONSP Cdr464)
>                 (LET ((Cdr463 (CDR Cdr464)))
>                   (IF (CONSP Cdr463)
>                       (IF (NULL (CDR Cdr463))
>                           (RETURN
>                            (s
>                             (LIST (CAR V154) (simplify (CAR Cdr464))
>                                   (simplify (CAR Cdr463)))))
>                           (GO tag459))
>                       (GO tag459)))
>                 (GO tag459))))
>      tag459
>       (RETURN V154))))
>
> (DEFUN s (V155)
>   (BLOCK NIL
>     (TAGBODY
>       (IF (CONSP V155)
>           (LET ((Car514 (CAR V155)) (Cdr515 (CDR V155)))
>             (TAGBODY
>               (IF (EQ '+ Car514)
>                   (IF (CONSP Cdr515)
>                       (LET ((Car488 (CAR Cdr515)) (Cdr489 (CDR
> Cdr515)))
>                         (TAGBODY
>                           (IF (CONSP Cdr489)
>                               (LET ((Car487 (CAR Cdr489)))
>                                 (IF (NULL (CDR Cdr489))
>                                     (IF (AND (NUMBERP Car488) (NUMBERP
> Car487))
>                                         (RETURN (THE NUMBER (+ Car488
> Car487)))
>                                         (GO tag468))
>                                     (GO tag468))))
>                          tag468
>                           (TAGBODY
>                             (IF (EQL 0 Car488)
>                                 (IF (CONSP Cdr489)
>                                     (IF (NULL (CDR Cdr489))
>                                         (RETURN (CAR Cdr489)) (GO
> tag471))
>                                     (GO tag471)))
>                            tag471
>                             (IF (CONSP Cdr489)
>                                 (LET ((Car485 (CAR Cdr489))
>                                       (Cdr486 (CDR Cdr489)))
>                                   (TAGBODY
>                                     (IF (EQL 0 Car485)
>                                         (IF (NULL Cdr486) (RETURN
> Car488)
>                                             (GO tag475)))
>                                    tag475
>                                     (IF (CONSP Car485)
>                                         (LET ((Cdr484 (CDR Car485)))
>                                           (IF (EQ '+ (CAR Car485))
>                                               (IF (CONSP Cdr484)
>                                                   (LET ((Cdr483 (CDR
> Cdr484)))
>                                                     (IF (CONSP Cdr483)
>                                                         (IF (NULL (CDR
> Cdr483))
>                                                             (IF (NULL
> Cdr486)
>
> (RETURN
>                                                                  (CONS
> '+
>
> (CONS
>
> (LIST
>
> '+
>
> Car488
>
> (CAR
>
> Cdr484
> ))
>
> Cdr483))
> )
>                                                                 (GO
> tag466))
>                                                             (GO
> tag466))
>                                                         (GO tag466)))
>                                                   (GO tag466))
>                                               (GO tag466)))
>                                         (GO tag466))))
>                                 (GO tag466)))))
>                       (GO tag466)))
>              tag466
>               (IF (EQ '* Car514)
>                   (IF (CONSP Cdr515)
>                       (LET ((Car512 (CAR Cdr515)) (Cdr513 (CDR
> Cdr515)))
>                         (TAGBODY
>                           (IF (CONSP Cdr513)
>                               (LET ((Car511 (CAR Cdr513)))
>                                 (IF (NULL (CDR Cdr513))
>                                     (IF (AND (NUMBERP Car512) (NUMBERP
> Car511))
>                                         (RETURN (THE NUMBER (* Car512
> Car511)))
>                                         (GO tag492))
>                                     (GO tag492))))
>                          tag492
>                           (TAGBODY
>                             (IF (EQL 0 Car512)
>                                 (IF (CONSP Cdr513)
>                                     (IF (NULL (CDR Cdr513)) (RETURN 0)
>                                         (GO tag495))
>                                     (GO tag495)))
>                            tag495
>                             (IF (CONSP Cdr513)
>                                 (LET ((Car509 (CAR Cdr513))
>                                       (Cdr510 (CDR Cdr513)))
>                                   (TAGBODY
>                                     (IF (EQL 0 Car509)
>                                         (IF (NULL Cdr510) (RETURN 0)
>                                             (GO tag499)))
>                                    tag499
>                                     (IF (CONSP Car509)
>                                         (LET ((Cdr508 (CDR Car509)))
>                                           (IF (EQ '* (CAR Car509))
>                                               (IF (CONSP Cdr508)
>                                                   (LET ((Cdr507 (CDR
> Cdr508)))
>                                                     (IF (CONSP Cdr507)
>                                                         (IF (NULL (CDR
> Cdr507))
>                                                             (IF (NULL
> Cdr510)
>
> (RETURN
>                                                                  (CONS
>
> (LIST Car512
>
> '*
>
> (CAR
>
> Cdr508)
> )
>
> (CONS '*
>
> Cdr507))
> )
>                                                                 (GO
> tag465))
>                                                             (GO
> tag465))
>                                                         (GO tag465)))
>                                                   (GO tag465))
>                                               (GO tag465)))
>                                         (GO tag465))))
>                                 (GO tag465)))))
>                       (GO tag465))
>                   (GO tag465)))))
>      tag465
>       (RETURN V155))))
>
> Mark

Oops should have written

[* A [* B C]] -> [* [* A B] C]

instead of

[* A [* B C]] -> [[A * B] * C]

post-editing infix to prefix I missed this.

However on re-running timings remain unchanged.

Mark
From: Alan Crowe
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <86zm24tqq6.fsf@cawtech.freeserve.co.uk>
Mark Tarver <··········@ukonline.co.uk> writes:

> This test was conducted to determine the relative efficiency of hand-
> coded Lisp, OCaml, Qi 8.0 and Qi Turbo-E using the benchmark challenge
> provided by Jon Harrop. 

> The problem is to simplify symbolic expressions by applying the
> following rewrite rules from the leaves up:

> 1*f -> f
> f*1 -> f

> The Solutions
> --------------------
> 
> Language: Qi
> Author: Mark Tarver
> Length: 13 lines
> 
> (define simplify
>   [Op A B] -> (s [Op (simplify A) (simplify B)])
>   A -> A)
> 
> (define s
>   [+ M N] -> (+ M N)	where (and (number? M) (number? N))
>   [+ 0 F] -> F
>   [+ F 0] -> F
>   [+ A [+ B C]] -> [+ [+ A B] C]
>   [* M N] -> (* M N)	where (and (number? M) (number? N))
>   [* 0 F] -> 0
>   [* F 0] -> 0
>   [* A [* B C]] -> [[A * B] * C]
>   A -> A)
> 

I think you are missing

[* 1 F] -> F 

and its commutative friend.

I doubt it will change the timings, but I know you will want
the code to be correct.

Alan Crowe
Edinburgh
Scotland
From: Mark Tarver
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <1184073545.202276.224510@22g2000hsm.googlegroups.com>
On 10 Jul, 12:58, Alan Crowe <····@cawtech.freeserve.co.uk> wrote:
> Mark Tarver <··········@ukonline.co.uk> writes:
> > This test was conducted to determine the relative efficiency of hand-
> > coded Lisp, OCaml, Qi 8.0 and Qi Turbo-E using the benchmark challenge
> > provided by Jon Harrop.
> > The problem is to simplify symbolic expressions by applying the
> > following rewrite rules from the leaves up:
> > 1*f -> f
> > f*1 -> f
> > The Solutions
> > --------------------
>
> > Language: Qi
> > Author: Mark Tarver
> > Length: 13 lines
>
> > (define simplify
> >   [Op A B] -> (s [Op (simplify A) (simplify B)])
> >   A -> A)
>
> > (define s
> >   [+ M N] -> (+ M N)    where (and (number? M) (number? N))
> >   [+ 0 F] -> F
> >   [+ F 0] -> F
> >   [+ A [+ B C]] -> [+ [+ A B] C]
> >   [* M N] -> (* M N)    where (and (number? M) (number? N))
> >   [* 0 F] -> 0
> >   [* F 0] -> 0
> >   [* A [* B C]] -> [[A * B] * C]
> >   A -> A)
>
> I think you are missing
>
> [* 1 F] -> F
>
> and its commutative friend.
>
> I doubt it will change the timings, but I know you will want
> the code to be correct.
>
> Alan Crowe
> Edinburgh
> Scotland- Hide quoted text -
>
> - Show quoted text -

Yes indeed.  I missed those cases. In which case the code is

(define simplify
  [Op A B] -> (s [Op (simplify A) (simplify B)])
  A -> A)

(define s
  [+ M N] -> (+ M N)	where (and (number? M) (number? N))
  [+ 0 F] -> F
  [+ F 0] -> F
  [+ A [+ B C]] -> [+ [+ A B] C]
  [* M N] -> (* M N)	where (and (number? M) (number? N))
  [* 0 F] -> 0
  [* F 0] -> 0
  [* F 1] -> F
  [* 1 F] -> F
  [* A [* B C]] -> [* [* A B] C]
  A -> A)

On 3 runs we get

(1-) (tt 1000000)

Evaluation took:
  0.656 seconds of real time
  0.59375 seconds of user run time
  0.0625 seconds of system run time
  [Run times include 0.047 seconds GC run time.]
  0 calls to %EVAL
  0 page faults and
  119,997,552 bytes consed.
0

(2-) !!

1. (tt 1000000)
Evaluation took:
  0.594 seconds of real time
  0.59375 seconds of user run time
  0.0 seconds of system run time
  0 calls to %EVAL
  0 page faults and
  119,993,336 bytes consed.
0

(3-) !!

2. (tt 1000000)
Evaluation took:
  0.609 seconds of real time
  0.609375 seconds of user run time
  0.0 seconds of system run time
  [Run times include 0.031 seconds GC run time.]
  0 calls to %EVAL
  0 page faults and
  120,001,224 bytes consed.
0

As you say, very little difference.

Mark
From: ctnd
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <1184159547.315078.137970@o61g2000hsh.googlegroups.com>
On Jul 10, 11:06 am, Mark Tarver <··········@ukonline.co.uk> wrote:
> This test was conducted to determine the relative efficiency of hand-
> coded Lisp, OCaml, Qi 8.0 and Qi Turbo-E using the benchmark challenge
> provided by Jon Harrop.  Dr Harrop also provided the
> Lisp source written by Andre Thieme, Nathan Forster and Pascal
> Constanza.
>
> Turbo-E is an unreleased version of Qi which factorises its pattern-
> matching.
>
> Jon Harrop Challenge Problem
> --------------------------------------------
>
> Posted by Dr Harrop
>
> http://groups.google.co.uk/group/comp.lang.lisp/browse_thread/thread/...
>
> The problem is to simplify symbolic expressions by applying the
> following rewrite rules from the leaves up:
>
> rational n + rational m -> rational(n + m)
> rational n * rational m -> rational(n * m)
> symbol x -> symbol x
> 0+f -> f
> f+0 -> f
> 0*f -> 0
> f*0 -> 0
> 1*f -> f
> f*1 -> f
> a+(b+c) -> (a+b)+c
> a*(b*c) -> (a*b)*c
>
> The Solutions
> --------------------
>
> Language: Qi
> Author: Mark Tarver
> Length: 13 lines
>
> (define simplify
>   [Op A B] -> (s [Op (simplify A) (simplify B)])
>   A -> A)
>
> (define s
>   [+ M N] -> (+ M N) where (and (number? M) (number? N))
>   [+ 0 F] -> F
>   [+ F 0] -> F
>   [+ A [+ B C]] -> [+ [+ A B] C]
>   [* M N] -> (* M N) where (and (number? M) (number? N))
>   [* 0 F] -> 0
>   [* F 0] -> 0
>   [* A [* B C]] -> [[A * B] * C]
>   A -> A)
>
> * Note I have used prefix notation for this problem though Dr Harrop's
> formulation uses infix. It does make a lot of difference to the
> timings. The Lisp solutions follow prefix and so I chose to make my
> program comparable.*
>
> *********************************************************
> Language: OCaml
> Author: Jon Harrop
> Length: 15 lines
>
> let rec ( +: ) f g = match f, g with
>   | `Int n, `Int m -> `Int (n +/ m)
>   | `Int (Int 0), e | e, `Int (Int 0) -> e
>   | f, `Add(g, h) -> f +: g +: h
>   | f, g -> `Add(f, g)
>
> let rec ( *: ) f g = match f, g with
>   | `Int n, `Int m -> `Int (n */ m)
>   | `Int (Int 0), e | e, `Int (Int 0) -> `Int (Int 0)
>   | `Int (Int 1), e | e, `Int (Int 1) -> e
>   | f, `Mul(g, h) -> f *: g *: h
>   | f, g -> `Mul(f, g)
>
> let rec simplify = function
>   | `Int _ | `Var _ as f -> f
>   | `Add (f, g) -> simplify f +: simplify g
>   | `Mul (f, g) -> simplify f *: simplify g
> ********************************************************************
> Language: Lisp
> Author: Andre Thieme
> Length: 23 lines
>
> (defun simplify (a)
>    (if (atom a)
>        a
>        (destructuring-bind (op x y) a
>         (let* ((f (simplify x))
>                (g (simplify y))
>                (nf (numberp f))
>                (ng (numberp g))
>                (+? (eq '+ op))
>                (*? (eq '* op)))
>           (cond
>             ((and +? nf ng)                   (+ f g))
>             ((and +? nf (zerop f))            g)
>             ((and +? ng (zerop g))            f)
>             ((and (listp g) (eq op (first g)))
>              (destructuring-bind (op2 u v) g
>                (simplify `(,op (,op ,f ,u) ,v))))
>             ((and *? nf ng)                   (* f g))
>             ((and *? (or (and nf (zerop f))
>                          (and ng (zerop g)))) 0)
>             ((and *? nf (= 1 f))              g)
>             ((and *? ng (= 1 g))              f)
>             (t                                `(,op ,f ,g)))))))
>
> ********************************************************************
> Language: Lisp
> Author: Nathan Froyd
> Length: 42 lines
>
> (defun simplify-no-redundant-checks (xexpr)
>   (declare (optimize (speed 3)))
>   (if (atom xexpr)
>       xexpr
>       (let ((op (first xexpr))
>             (z (second xexpr))
>             (y (third xexpr)))
>         (let* ((f (simplify-no-redundant-checks z))
>                (g (simplify-no-redundant-checks y))
>                (nf (numberp f))
>                (ng (numberp g)))
>           (tagbody
>            START
>              (if (eq '+ op) (go OPTIMIZE-PLUS) (go TEST-MULTIPLY))
>            OPTIMIZE-PLUS
>              (when (and nf ng) (return-from simplify-no-redundant-
> checks (+
> f g)))
>            TEST-PLUS-ZEROS
>              (when (eql f 0) (return-from simplify-no-redundant-checks
> g))
>              (when (eql g 0) (return-from simplify-no-redundant-checks
> f))
>              (go REARRANGE-EXPR)
>            TEST-MULTIPLY
>              (unless (eq '* op) (go REARRANGE-EXPR))
>            OPTIMIZE-MULTIPLY
>              (when (and nf ng) (return-from simplify-no-redundant-
> checks (*
> f g)))
>            TEST-MULTIPLY-ZEROS-AND-ONES
>              (when (or (eql f 0) (eql g 0)) (return-from
> simplify-no-redundant-checks 0))
>              (when (eql f 1) (return-from simplify-no-redundant-checks
> g))
>              (when (eql g 1) (return-from simplify-no-redundant-checks
> f))
>            REARRANGE-EXPR
>              (when (and (listp g) (eq op (first g)))
>                (let ((op2 (first g))
>                      (u (second g))
>                      (v (third g)))
>                  (declare (ignore op2))
>                  (return-from simplify-no-redundant-checks
>                    (simplify-no-redundant-checks (list op (list op f
> u)
> v)))))
>            MAYBE-CONS-EXPR
>              (if (and (eq f z) (eq g y))
>                  (return-from simplify-no-redundant-checks xexpr)
>                  (return-from simplify-no-redundant-checks (list op f
> g))))))))
>
> ********************************************************************
> Language: Lisp
> Author: Pascal Constanza
> Length: 27 lines
>
> (defstruct add x y)
> (defstruct mul x y)
>
> (defgeneric simplify-add (x y)
>   (declare (optimize (speed 3)))
>    (:method ((x number) (y number)) (+ x y))
>    (:method ((x (eql 0)) y) y)
>    (:method (x (y (eql 0))) x)
>    (:method (x (y add))
>     (simplify-add (simplify-add x (add-x y)) (add-y y)))
>    (:method (x y) (make-add :x x :y y)))
>
> (defgeneric simplify-mul (x y)
>   (declare (optimize (speed 3)))
>    (:method ((x number) (y number)) (* x y))
>    (:method ((x (eql 0)) y) 0)
>    (:method (x (y (eql 0))) 0)
>    (:method ((x (eql 1)) y) y)
>    (:method (x (y (eql 1))) x)
>    (:method (x (y mul))
>     (simplify-mul (simplify-mul x (mul-x y)) (mul-y y)))
>    (:method (x y) (make-mul :x x :y y)))
>
> (defgeneric simplify (exp)
>   (declare (optimize (speed 3)))
>    (:method (exp) exp)
>    (:method ((exp add))
>     (simplify-add (simplify (add-x exp)) (simplify (add-y exp))))
>    (:method ((exp mul))
>     (simplify-mul (simplify (mul-x exp)) (simplify (mul-y exp)))))
>
> The Results
> ------------------
>
> All Qi/Lisp programs were running under Windows SBCL 1.0. The platform
> was a 2.6 GHz Intel PC with 500 Mb of main memory.  The challenge was
> to simplify [* x [+ [+ [* 12 0] [+ 23 8]] y]].
> 10^6 iterations were used as the benchmark.
>
> Qi 8.0     Qi Turbo-E   Nathan  Andre   Pascal  Jon
> *******************************************************************
> 0.9s    0.625s  0.49s   1.59s   0.09s   ?
>
> Evaluation
> -----------------
>
> Missing is Jon Harrop's OCaml version.  I'm not into OCaml enough to
> know how to run and time this program.
>
> ====> Any takers out there to fill in the gap?
>
> Jon says himself that
>
> '....Lisp's fastest time is only 3x slower than the OCaml (using
> Nathan's hand-optimised pattern match)'
>
> However Nathan's hand-optimised pattern match is not the fastest
> version.  That honour goes to Pascal's version which seems to be on a
> par with OCaml taking Jon's assessment as correct.  However
> elsewhere Jon says
>
> 'The fastest Lisp implementation to date was written by Pascal
> Constanza. It is also quite elegant but still 3x slower than the
> OCaml. More interestingly, it avoids s-exprs:...'
>
> Perhaps a slip of the pen here.  Perhaps he meant that OCaml is 3X
> faster than Pascal's program.
>
> Addendum: The Qi program under Turbo-E compiles into 119 lines of Lisp
>
> (DEFUN simplify (V154)
>   (BLOCK NIL
>     (TAGBODY
>       (IF (CONSP V154)
>           (LET ((Cdr464 (CDR V154)))
>             (IF (CONSP Cdr464)
>                 (LET ((Cdr463 (CDR Cdr464)))
>                   (IF (CONSP Cdr463)
>                       (IF (NULL (CDR Cdr463))
>                           (RETURN
>                            (s
>                             (LIST (CAR V154) (simplify (CAR Cdr464))
>                                   (simplify (CAR Cdr463)))))
>                           (GO tag459))
>                       (GO tag459)))
>                 (GO tag459))))
>      tag459
>       (RETURN V154))))
>
> (DEFUN s (V155)
>   (BLOCK NIL
>     (TAGBODY
>       (IF (CONSP V155)
>           (LET ((Car514 (CAR V155)) (Cdr515 (CDR V155)))
>             (TAGBODY
>               (IF (EQ '+ Car514)
>                   (IF (CONSP Cdr515)
>                       (LET ((Car488 (CAR Cdr515)) (Cdr489 (CDR
> Cdr515)))
>                         (TAGBODY
>                           (IF (CONSP Cdr489)
>                               (LET ((Car487 (CAR Cdr489)))
>                                 (IF (NULL (CDR Cdr489))
>                                     (IF (AND (NUMBERP Car488) (NUMBERP
> Car487))
>                                         (RETURN (THE NUMBER (+ Car488
> Car487)))
>                                         (GO tag468))
>                                     (GO tag468))))
>                          tag468
>                           (TAGBODY
>                             (IF (EQL 0 Car488)
>                                 (IF (CONSP Cdr489)
>                                     (IF (NULL (CDR Cdr489))
>                                         (RETURN (CAR Cdr489)) (GO
> tag471))
>                                     (GO tag471)))
>                            tag471
>                             (IF (CONSP Cdr489)
>                                 (LET ((Car485 (CAR Cdr489))
>                                       (Cdr486 (CDR Cdr489)))
>                                   (TAGBODY
>                                     (IF (EQL 0 Car485)
>                                         (IF (NULL Cdr486) (RETURN
> Car488)
>                                             (GO tag475)))
>                                    tag475
>                                     (IF (CONSP Car485)
>                                         (LET ((Cdr484 (CDR Car485)))
>                                           (IF (EQ '+ (CAR Car485))...
>
> read more �

Lisp is a language separate from its _implementations_... what?
From: Larry Clapp
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <slrnf99thn.a69.larry@theclapp.ddts.net>
On 2007-07-11, ctnd <·········@googlemail.com> wrote:
> On Jul 10, 11:06 am, Mark Tarver <··········@ukonline.co.uk> wrote:
[ 304 lines snipped ]
>
> Lisp is a language separate from its _implementations_... what?

Why must you quote 304 lines to ask a one-line question?
From: Madhu
Subject: Re: Jon Harrop rewrite benchmark; Qi, Lisp and OCaml
Date: 
Message-ID: <m31wfey2yq.fsf@robolove.meer.net>
* Larry Clapp  <····················@theclapp.ddts.net> :

| On 2007-07-11, ctnd <·········@googlemail.com> wrote:
|> On Jul 10, 11:06 am, Mark Tarver <··········@ukonline.co.uk> wrote:
| [ 304 lines snipped ]
|>
|> Lisp is a language separate from its _implementations_... what?
|
| Why must you quote 304 lines to ask a one-line question?

Because he's using google groups and they design the UI to encourage him
to do that.

--
Madhu
*murmur investments in bandwidth industry* *lost time scrolling*