Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to type DO variables in common lisp?

I know you can declare function parameter types like

(defun add-integer (a b)
  (declare (integer a b))
  (the integer (+ a b)))

But what about DO variables? For example, I want to type passes:

(defun bench ()
  (do ((end (+ (get-internal-real-time) (* 5 internal-time-units-per-second)))
       (passes 0 (+ 1 passes)))
      ((> (get-internal-real-time) end)
       passes)
    (sieve 1000000)))

When I try to compile with (declaim (optimize (speed 2) (safety 0))), I get

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

; in: DEFUN BENCH
;     (1+ PASSES)
; 
; note: forced to do full call
;       unable to do inline fixnum arithmetic (cost 2) because:
;       The first argument is a UNSIGNED-BYTE, not a FIXNUM.
;       The result is a (VALUES (INTEGER 1) &OPTIONAL), not a (VALUES FIXNUM
;                                                                     &REST T).
;       unable to do inline (unsigned-byte 64) arithmetic (cost 5) because:
;       The first argument is a UNSIGNED-BYTE, not a (UNSIGNED-BYTE 64).
;       The result is a (VALUES (INTEGER 1) &OPTIONAL), not a (VALUES
;                                                              (UNSIGNED-BYTE 64)
;                                                              &REST T).

I tried

(defun bench ()
  (declare (type (unsigned-byte 64) passes))
  (do ((end (+ (get-internal-real-time) (* 5 internal-time-units-per-second)))
       (passes 0 (+ 1 passes)))
      ((> (get-internal-real-time) end)
       passes)
    (sieve 1000000)))

But then I get

;   Undefined variable:
;     PASSES

I cannot find anything on this in the type chapters of the HyperSpec, e.g. (http://clhs.lisp.se/Body/04_bc.htm). A working example would be extremely helpful! Thanks!

>Solution :

You put the declaration at the beginning of the loop body.

(defun bench ()
  (do ((end (+ (get-internal-real-time) (* 5 internal-time-units-per-second)))
       (passes 0 (+ 1 passes)))
      ((> (get-internal-real-time) end)
       passes)
    (declare (type (unsigned-byte 64) passes))
    (sieve 1000000)))

This is shown in the specification of DO:

do ({var | (var [init-form [step-form]])}*) (end-test-form result-form*) declaration* {tag | statement}*

See declaration after (end-test-form result-form*)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading