英単語覚えるスクリプト

Shibuya.lisp の発表で少し触れた、英単語覚えるスクリプトを改善した。毎日使っていて単語量が増えたので誤り回数が多い物順に出題する事にした。

(import (rnrs)
        (mosh control)
        (mosh)
        (match)
        (mosh file)
        (srfi :8)
        (only (srfi :1) first second))

(define (sort-word-spec* word-spec*)
  (list-sort
   (match-lambda*
    [((_a _b ok-count1 ng-count1) (_c _d ok-count2 ng-count2))
     (> (- ng-count1 ok-count1) (- ng-count2 ok-count2))])
   ;; normalization
   (map (match-lambda
          [(word meaning)
           (list word meaning 0 0)]
          [(word meaning ok-count ng-count)
           (list word meaning ok-count ng-count)])
        word-spec*)))

(define (main args)
  (let1 result*
      (call/cc
       (lambda (break)
         (let loop ([word-spec* (sort-word-spec* (file->sexp-list (second args)))]
                    [result-spec* '()])
           (match word-spec*
             [() result-spec*]
             [((word meaning ok-count ng-count) . more)
              (format #t "~s: " word)
              (read (current-input-port))
              (format #t "~s y/n? " meaning)
              (case (read-char (current-input-port))
                [(#\y #\Y)
                 (loop more (cons (list word meaning (+ ok-count 1) ng-count) result-spec* ))]
                [(#\N #\n)
                 (loop more (cons (list word meaning ok-count (+ ng-count 1)) result-spec*))]
                [(#\q #\Q)
                 (break (append (reverse result-spec*) word-spec*))])])]))
    (call-with-port (open-file-output-port (second args) (make-file-options '(no-fail)) 'block (native-transcoder))
                    (lambda (p)
                      (for-each (lambda (x)
                                  (write x p)
                                  (newline p)) result*)))))

(main (command-line))

match-lambda を使っているのは Erlang で便利さに気づいたから。