One way CL doesn't suck (was Re: How Common Lisp sucks)
- From: Christophe Rhodes <csr21@xxxxxxxxx>
- Date: Tue, 18 Apr 2006 15:54:09 +0100
Peter Seibel <peter@xxxxxxxxxxxxxxx> writes:
Christophe Rhodes <csr21@xxxxxxxxx> writes:
Peter Seibel <peter@xxxxxxxxxxxxxxx> writes:
Now let's see what effect some declarations have:
CL-USER> (defun foo (x y)
(declare (optimize (speed 3) (safety 0)))
(declare (fixnum x y))
(+ x y))
FOO
CL-USER> (disassemble 'foo)
;; disassembly of #<Function (:ANONYMOUS-LAMBDA 13) @ #x107c84c2>
;; formals: X Y
;; code start: #x107c84a4:
0: 7c632014 addc r3,r3,r4
4: 3a000001 [addi] lil r16,1
8: 81a1000c lwz r13,12(r1)
12: 4e800020 blr
Isn't this quite a bad example to use when demonstrating things for a
newbie, given that it is nonconforming output? [ I believe Allegro
documents this deviation, but try (foo most-positive-fixnum
most-positive-fixnum) ]
Sure. Out of curiosity, is it non-conforming given that I declared
safety 0? Or is the implementation still required to produce correct
results?
Yes. 0 safety does not permit an implementation which purports to
conform to ANSI to give the wrong results if none of the constraints
(including user type declarations) are violated. [ My interpretation
of the spec only, yadda yadda; the good people at Franz may not have
more pedantic language lawyers, but they almost certainly have better
law lawyers :-) ]
Which would mean I'd technically have to explicitly mask the
result of (+ x y) down to fixnum bits. And then Allegro doesn't
optimize away the LOGAND. Does SBCL. I.e. if I write:
(defun foo (x y)
(declare (optimize (speed 3) (safety 0)))
(declare (fixnum x y))
(the fixnum (logand (+ x y) #.(1- (expt 2 (integer-length most-positive-fixnum))))))
Well, no, but that's because here your LOGAND doesn't do what I think
you think it does, because a FIXNUM is a signed quantity. The LOGAND
isn't optimized away, but it does compile to two machine instructions
(x86 this time):
; 0A85BCEC: 01FA ADD EDX, EDI ; no-arg-parsing entry point
; CEE: 81E2FFFFFF1F AND EDX, 536870911
; [+ return sequence ]
If instead you do
(defun sfoo (x y)
(declare (optimize (speed 3) (safety 0)))
(declare (fixnum x y))
(sb-c::mask-signed-field 30 (+ x y))) ; 30 fixnum bits on x86
you get just the add:
; 0AA4221E: 01FA ADD EDX, EDI ; no-arg-parsing entry point
; [+ return sequence ]
MASK-SIGNED-FIELD, or some equivalent, will eventually make it to
documented and exported status in SBCL, because this is a thing that
Lisp coders want to do; the contortion of an extra operator is needed
because there's no signed equivalent to LOGAND or LDB, which express
the equivalent unsigned operation.
I wouldn't recommend using FIXNUM declarations, though; they're not
only machine-dependent but implementation-dependent too. Use
(signed-byte 32) or (unsigned-byte 32) (or 64 bits, if that's what
your algorithm needs, or (signed-byte 19) come to that).
Christophe
.
- Follow-Ups:
- Re: One way CL doesn't suck (was Re: How Common Lisp sucks)
- From: Peter Seibel
- Re: One way CL doesn't suck (was Re: How Common Lisp sucks)
- References:
- How Common Lisp sucks
- From: Ron Garret
- Re: How Common Lisp sucks
- From: bradb
- Re: How Common Lisp sucks
- From: Peter Seibel
- Re: How Common Lisp sucks
- From: bradb
- Re: How Common Lisp sucks
- From: Peter Seibel
- Re: How Common Lisp sucks
- From: Christophe Rhodes
- Re: How Common Lisp sucks
- From: Peter Seibel
- How Common Lisp sucks
- Prev by Date: Re: why 100% cpu usage
- Next by Date: Re: How Common Lisp sucks
- Previous by thread: Re: How Common Lisp sucks
- Next by thread: Re: One way CL doesn't suck (was Re: How Common Lisp sucks)
- Index(es):
Relevant Pages
|