Here's a somewhat-optimized version of the code:
#lang racket/base
(require racket/string racket/vector racket/port)
(define h (make-hash))
(time
(for* ([l (in-lines)]
[w (in-list (string-split l))]
[w* (in-value (string-downcase w))])
(hash-update! h w* add1 0)))
(define v
(time
(for/vector #:length (hash-count h)
([(k v) (in-hash h)])
(cons k v))))
(time (vector-sort! v > #:key cdr))
(define p (current-output-port) #;(open-output-nowhere))
(time
(for ([pair (in-vector v)])
(write-string (car pair) p)
(write-string (number->string (cdr pair)) p)
(newline p)))
It's much more imperative, but also pretty nice and compact. The
`printf` optimization is significant for that portion of the program,
but that isn't much of the running time. The overall running time for
10 copies of the KJV is about 9 seconds on my laptop.
I think the remaining difference between Racket and other languages is
likely the `string-split` and `string-downcase` functions, plus the
relatively-inefficient string representation that Racket uses.
Sam
> To view this discussion on the web visit
https://groups.google.com/d/msgid/racket-users/09c58a34-bd2d-49e7-bfbd-d3253c1e6dd1n%40googlegroups.com.