Hacker News new | ask | show | jobs
by dig1 2338 days ago
I believe I'm missing something here or my day was too long, but in Clojure this can be squeezed in 13 lines and 435 characters keeping things fairly readable (for Clojure & Lisp developers ;)).

    (defn wc [^String file]
      (with-open [rdr (clojure.java.io/reader file)]
        (apply (partial printf "%d %d %d\n")
               (reduce
                (fn [[nl nw nb] ^String ln]
                  (let [words (count (.split ln "[ ]+"))
                        bytes (alength (.getBytes ln "UTF-8"))]
                    [(inc nl) (+ nw words) (+ nb bytes)]))
                [0 0 0]
                (line-seq rdr)))))
    
    (defn -main [& args]
      (wc (first args)))

I haven't tested how fast it is, but startup time can be optimized by compiling it with GraalVM.
2 comments

Neat! I wonder if the character decoding & regex usage has noticeable performance impact. My Common Lisp version was sped up somewhat by switching from a character stream to a byte stream: https://git.tazj.in/tree/fun/wcl/wc.lisp

You can try this one via Nix with:

  nix-build -E '(import (builtins.fetchGit "https://git.tazj.in") {}).fun.wcl'
It's been a while since I last wrote CL but I think your program can produce any counts between zero and the correct one – you need to use eql instead of eq if you want this to work in standard common lisp.
Ah, you're right of course - fixed. Though that still won't make this portable, as I'm using an SBCL-specific way of accessing argv.
`unix-opts` is in available in quicklisp -- it's small, and has a portable `argv` wrapper function.
That's a very impressive Nix configuration. Nicely done!
Since we're golfing, here's a 51-character version in fairly readable J:

    wc=:[:+/[:(1:,([:#'\S+'&rxmatches),>:@#);._2 freads
I'm guessing that a real J wizard could squeeze out a few more characters. :)