Re: static, dynamic and implicitely typed languages



Rainer Joswig <joswig@xxxxxxx> wrote:
+---------------
| rpw3@xxxxxxxx (Rob Warnock) wrote:
| > Chris Barts <chbarts+usenet@xxxxxxxxx> wrote:
| > +---------------
| > | You can also explicitly declare the types of variables,
| > | as in this function: ...
| > +---------------
| >
| > To really get the maximum speed, you have to be able to assure the
| > compiler that the *result* of multiplying B by 2 will also still be
| > a FIXNUM. If you *are* sure of that, then you can tell a CL compiler
| > about it this way:
| >
| > (defun foo (a b c)
| > (declare (type number a)
| > (type fixnum b)
| > (type cons c))
| > (cons (+ a (the fixnum (* 2 b))) c))
| >
| > As you note, this may not be of much benefit, since the compiler
| > will still have to use fully-generic "+" when adding "A"... :-{
|
| But see this (simplifying your example):
+---------------

[Chris Barts's example, actually...]

+---------------
| (defun foo (a b)
| (declare (type number a)
| (type fixnum b))
| (+ a (the fixnum (* 2 b))))
+---------------

That's just what I wrote above, less the CONS with C.

+---------------
| (defun bar (a b c)
| (declare (type fixnum a b c)
| (inline foo))
| (the fixnum (+ a (foo b c))))
+---------------

But A was given in the original example as a NUMBER, *not* a FIXNUM!
You can't just change the rules in the middle like that.

+---------------
| Which can be seen as something like this:
|
| (defun foobar (a b c)
| (declare (type fixnum a b c))
| (the fixnum (+ a (+ b (the fixnum (* 2 c))))))
|
| So the type of the arguments gets propagated into inlined functions.
| So, FOO may use a generic +. But BAR may use a FIXNUM +
| in the inlined code of FOO.
+---------------

(*sigh*) Even if you change the rules so that A is a FIXNUM
(not a NUMBER), your re-write *still* isn't correct unless
you *know* that the intermediate sums are all still FIXNUMs!!
As it stands above, you're lying to the compiler. Even if you
*know* that the final result (+ A (+ B (THE FIXNUM (* 2 C))))
is a FIXNUM, you *DON'T* know [or, if you do know, you
haven't yet promised the compiler] that the intermediate sum
(+ B (THE FIXNUM (* 2 C))) is a FIXNUM. Consider what happens
when C is positive, B is MOST-POSITIVE-FIXNUM, and A is a
negative FIXNUM less than (- (* 2 C)). The sum with B will
push the intermediate result into a BIGNUM [*expensive!*],
but the sum with A will bring it back into the FIXNUM range.

But if you *know* that can't happen, you could tell the
compiler about it and make the code faster still:

(defun foobar (a b c)
(declare (type fixnum a b c))
(the fixnum (+ a (the fixnum (+ b (the fixnum (* 2 c)))))))

But in these kinds of cases it might be better to just tell
the compiler the actual value ranges of the variables, and
then you don't have to sprinkle THE around all over the place
[if the compiler's type propagation is smart enough], e.g.:

(defun foobar (a b c)
(declare (type (integer -1000 1000) a b)
(type (integer -500 500) c))
(+ a b (* 2 c))) ; *Must* be (INTEGER -3000 3000), so no THE needed.


-Rob

p.s. If you compile the latter with (SAFETY 0) in CMUCL, it will
even eliminate the range checks on the args, giving this code with
all the ops inlined (on x86):

48AEE540: .ENTRY "LAMBDA (A B C)"(a b c) ; (FUNCTION
; ((INTEGER -1000 1000) ..))
58: POP DWORD PTR [EBP-8]
5B: LEA ESP, [EBP-32]

5E: MOV EBX, EDX ; [:NON-LOCAL-ENTRY]

60: LEA EDX, [EBX+EDI] ; No-arg-parsing entry point
; [:NON-LOCAL-ENTRY]
63: LEA EAX, [ESI*2]
6A: ADD EDX, EAX

6C: MOV ECX, [EBP-8] ; [:BLOCK-START]
6F: MOV EAX, [EBP-4]
72: ADD ECX, 2
75: MOV ESP, EBP
77: MOV EBP, EAX
79: JMP ECX

-----
Rob Warnock <rpw3@xxxxxxxx>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

.



Relevant Pages

  • Re: Why doesnt Lisp automatically differentiate functions and macros?
    ... for starters functions and macros do fundamentally different ... the compiler is supposed to "know" that any system call (e.g. I/ ... (defun calculate-bit-position (metatype marker) ... (declare (fixnum result)) ...
    (comp.lang.lisp)
  • Re: How to Speed up Cellular Automata
    ... > it is evaluated at least in LispWorks. ... And foo can't be declared as fixnum either. ... I've added integer declares and "of-type ... > the the compiler produces more straightforward assembler code. ...
    (comp.lang.lisp)
  • One way CL doesnt suck (was Re: How Common Lisp sucks)
    ... CL-USER> (defun foo (x y) ... (declare (fixnum x y)) ... result of down to fixnum bits. ... Well, no, but that's because here your LOGAND doesn't do what I think ...
    (comp.lang.lisp)
  • Re: why is lisp fast?
    ... Why do you equate "wanting to compete ... of the addition as a fixnum if the user wishes to inform the system ... lisp objects. ... (declare (fixnums-remain-fixnum t)) ...
    (comp.lang.lisp)
  • Re: Prototype-based / Ruby question
    ... >> object's class) is the future of optimization in Ruby. ... >> call (in this hypothetical Ruby compiler). ... A derived class is overriding a method ... > that i is always a Fixnum" condition. ...
    (comp.lang.ruby)