chicken-scheme

Why does this program work on Chez Scheme but fail on Chicken Scheme?


When I run this program at Ideone:

; scrambled words

(define rand ; knuth random number generator with shuffle box
  (let* ((a 69069) (c 1234567) (m 4294967296) (k 32) ; 32-bit
         ; (a 6364136223846793005) (c 1442695040888963407)
         ; (m 18446744073709551616) (k 256) ; 64-bit
         (seed 19380110) ; happy birthday knuth
         (next (lambda ()
           (set! seed (modulo (+ (* a seed) c) m)) seed))
         (init (lambda (seed) (let ((box (make-vector k)))
           (do ((j 0 (+ j 1))) ((= j k) box)
             (vector-set! box j (next))))))
         (box (init seed)))
    (lambda args
      (if (pair? args)
        (set! seed (modulo (car args) m)) (set! box (init seed)))
      (let* ((j (quotient (* k seed) m)) (n (vector-ref box j)))
        (set! seed (next)) (vector-set! box j seed) (/ n m)))))

(define (randint . args)
  (let ((lo (if (pair? (cdr args)) (car args) 0))
        (hi (if (pair? (cdr args)) (cadr args) (car args))))
    (+ lo (floor (* (rand) (- hi lo))))))

(define (shuffle x)
  (do ((v (list->vector x)) (n (length x) (- n 1)))
      ((zero? n) (vector->list v))
    (let* ((r (randint n)) (t (vector-ref v r)))
      (vector-set! v r (vector-ref v (- n 1)))
      (vector-set! v (- n 1) t))))

(define (scramble str)
  (let* ((cs (string->list str))
         (upper (map char-upper-case? cs))
         (cs (map char-downcase cs)))
    (let loop ((cs cs) (word (list)) (zs (list)))
      (cond ((null? cs) ; end of input
              (list->string
                (map (lambda (u? c)
                       (if u? (char-upcase c) c))
                     upper (reverse zs))))
            ((char-alphabetic? (car cs)) ; in a word
              (loop (cdr cs) (cons (car cs) word) zs))
            ((pair? word) ; end of word
              (loop cs (list) (append (shuffle word) zs)))
            (else ; not in a word
              (loop (cdr cs) word (cons (car cs) zs)))))))

(display (scramble "Programming Praxis is fun!")) (newline)
(display (scramble "Programming Praxis is fun!")) (newline)
(display (scramble "Programming Praxis is fun!")) (newline)

I get this error output:

Error: (vector-ref) bad argument type: 1.0

    Call history:

    <eval>    [next] (+ (* a seed) c)
    <eval>    [next] (* a seed)
    <eval>    [init] (doloop14 (+ j 1))
    <eval>    [init] (+ j 1)
    <eval>    [init] (= j k)
    <eval>    (quotient (* k seed) m)
    <eval>    (* k seed)
    <eval>    (vector-ref box j)
    <eval>    (next)
    <eval>    [next] (modulo (+ (* a seed) c) m)
    <eval>    [next] (+ (* a seed) c)
    <eval>    [next] (* a seed)
    <eval>    (vector-set! box j seed)
    <eval>    (/ n m)
    <eval>    [randint] (- hi lo)
    <eval>    [shuffle] (vector-ref v r)    <--

Can someone please explain what is going wrong? And how to fix it?


Solution

  • This program generates very large integers. It looks like Ideone is using CHICKEN 4, which did not support arbitrarily large integers ("bignums" in Scheme parlance).

    When you get numbers too large to fit a machine word (minus 2 bits), CHICKEN 4 would stuff the number in a floating-point number in order to neatly overflow. That's why you get the vector-ref error.

    If ideone supports it, you could try adding (use numbers) at the start of your program. This numbers egg adds support for the full numeric tower (with several caveats) in CHICKEN 4.

    CHICKEN 5 supports the full numeric tower out of the box and the program works fine there, unmodified.