[racket] when is `listof` the better contract
In what situations should one prefer the `listof` combinator over an equivalent predicate contract?
For instance, it seems to me that:
(λ(x) (and (list? x) (andmap pred? x)))
is a more-or-less equivalent way of saying this:
(listof pred?)
But in my experience the predicate version is always significantly faster. Thus, is it generally better to rewrite contracts to avoid `listof`? And if so, when is `listof` still preferred?
;;;;;;;;;;;;;;;;;;;;;;
;; For instance.
;;;;;;;;;;;;;;;;;;;;;;
#lang racket
(define/contract (f1 xs)
((listof integer?) . -> . any/c)
xs)
(define (integers? x) (and (list? x) (andmap integer? x)))
(define/contract (f2 xs)
(integers? . -> . any/c)
xs)
(define (trial proc) (for ([i (in-range 1000)]) (proc (range 10000))))
(time (trial f1))
(time (trial f2))