Почему эта программа работает на Chez Scheme, но не работает на Chicken Scheme?

Когда я запускаю эту программу на 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)

Я получаю этот вывод ошибки:

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)    <--

Может кто-нибудь объяснить, что происходит не так? И как это исправить?


person user448810    schedule 07.10.2019    source источник


Ответы (1)


Эта программа генерирует очень большие целые числа. Похоже, что Ideone использует CHICKEN 4, который не поддерживает произвольно большие целые числа («bignums» на языке Scheme).

Когда вы получаете числа, слишком большие для машинного слова (минус 2 бита), CHICKEN 4 вставляет число в число с плавающей запятой, чтобы аккуратно переполниться. Вот почему вы получаете ошибку векторной ссылки.

Если ideone поддерживает это, вы можете попробовать добавить (use numbers) в начале вашей программы. Это яйцо с числами добавляет поддержку полной числовой башни (с некоторыми оговорками) в КУРИЦА 4.

CHICKEN 5 поддерживает полную числовую башню из коробки, и программа работает там нормально, без изменений.

person sjamaan    schedule 07.10.2019
comment
(используйте числа) не поддерживается в ideone. И числа используемые не большие, всего 32 бита. Я предполагаю, что некоторые из промежуточных чисел могут переполниться. - person user448810; 07.10.2019
comment
Я изменил программу, чтобы использовать встроенную функцию (random n). - person user448810; 07.10.2019
comment
Обратите внимание, что случайная функция в CHICKEN 4 полагается на C rand(), который дерьмовый. В CHICKEN 5 мы включили PRNG на основе WELL512 и используем системную энтропию (например, /dev/urandom в *nix) для заполнения случайными данными. - person sjamaan; 08.10.2019