(asdf:oos 'asdf:load-op 'drakma) (asdf:oos 'asdf:load-op 's-xml) ;; (asdf:oos 'asdf:load-op 'clot) (defpackage :code-index (:use :cl :clot :drakma :s-xml)) (in-package :code-index) (defun code-search (regexp &key language license file package (output-type :sxml)) (let ((url (concatenate 'string "http://google.com/codesearch/feeds/search?q=" (when language (concatenate 'string "lang:" language "+")) (when license (concatenate 'string "license:" license "+")) (when file (concatenate 'string "file:" file "+")) (when package (concatenate 'string "package:" package "+")) regexp))) (multiple-value-bind (body-or-stream status-code headers uri stream must-close reason-phrase) (drakma::http-request url :force-binary t) (declare (ignore headers must-close stream reason-phrase)) (format t "Request for ~A~%" uri) (format t "Status code ~A~%" status-code) (parse-xml-string (flexi-streams:octets-to-string body-or-stream :external-format (flexi-streams:make-external-format :utf-8)) )))) (defun code-search-hit-count (results) (parse-integer (cadr (nth 5 results)))) (defun calculate-index-for-language (lang) (format t "~&For Langauge : ~A~&" lang) (let* ((control-index (code-search-hit-count (code-search "okay" :language lang))) (suckage-index (/ (code-search-hit-count (code-search "sucks" :language lang)) control-index)) (rockage-index (/ (code-search-hit-count (code-search "rocks" :language lang)) control-index))) (format t "Suckage index ~D~&" suckage-index) (format t "Rockage index ~D~&" rockage-index) (format t "Controversy index ~F~&" (sqrt (+ (* rockage-index rockage-index) (* suckage-index suckage-index)))) ;; admittedly it's a bust if no one ever says that language Y sucks, but how probable is that ;-) (format t "Suckage/Rockage ratio ~D~&" (/ rockage-index suckage-index)))) ;; forth doesn't have enough hits (defun compare-languages () (mapcar #'calculate-index-for-language '("c" "ruby" "perl" "pascal" "erlang" "javascript" "java" "smalltalk" "python" "lisp" "haskell" "ocaml")))