What does clisp do behind the scene if you give it (* 2 2 2)

Discussion of Common Lisp
Kompottkin
Posts: 94
Joined: Mon Jul 21, 2008 7:26 am
Location: München, Germany
Contact:

Re: What does clisp do behind the scene if you give it (* 2 2 2)

Post by Kompottkin » Wed Jul 13, 2011 12:28 pm

yesimthetaxman wrote:If (* 2 2 2) is somehow converted to (* (* 2 2) 2), then that extra step used in the conversion would mean that technically it would take slightly longer for the CPU to compute right?
That's not what happens:

Code: Select all

[1]> (disassemble (lambda (x y z) (* x y z)))

Disassembly of function :LAMBDA
...
5 byte-code instructions:
0     (LOAD&PUSH 3)
1     (LOAD&PUSH 3)
2     (LOAD&PUSH 3)
3     (CALLSR 3 57)                       ; *
6     (SKIP&RET 4)
NIL

Code: Select all

[2]> (disassemble (lambda (x y z) (* (* x y) z)))

Disassembly of function :LAMBDA
...
6 byte-code instructions:
0     (LOAD&PUSH 3)
1     (LOAD&PUSH 3)
2     (CALLSR&PUSH 2 57)                  ; *
5     (LOAD&PUSH 2)
6     (CALLSR 2 57)                       ; *
9     (SKIP&RET 4)
NIL
Now, what does (CALLSR 3 57) do? Let's have a look at the FUNTABR structure in eval.d. The 57th entry, along with the comment above it, tells us that we're looking for the star function in lisparit.d. Its implementation is:

Code: Select all

LISPFUN(star,seclass_foldable,0,0,rest,nokey,0,NIL)
{ /* (* {number}), CLTL p. 199
     method:
     (*) = 1
     (* x1 x2 x3 ... xn) = (* ...(* (* x1 x2) x3)... xn) */
  if (argcount==0) {
    VALUES1(Fixnum_1); return;
  }
  argcount--;
  test_number_args(argcount,rest_args_pointer); /* all arguments numbers? */
  /* method:
     n+1 arguments Arg[0..n].
     x:=Arg[0], for i:=1 to n do ( x := x*Arg[i] ), return(x). */
  var gcv_object_t* arg_i_ptr = rest_args_pointer;
  var object x = NEXT(arg_i_ptr); /* product so far */
  dotimesC(argcount,argcount, {
    var object arg = NEXT(arg_i_ptr);
    x = (eq(x,arg) ? N_square_N(x) : N_N_mult_N(x,arg));
  });
  VALUES1(x); set_args_end_pointer(rest_args_pointer);
}
I'm not an expert in CLISP internals, but I would naïvely guess that a single dotimesC loop is probably slightly more efficient than having to call the star function twice.

Post Reply