Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2008-01-16

Lispの変な関数名

| 01:07 | Lispの変な関数名 - わだばLisperになる を含むブックマーク はてなブックマーク - Lispの変な関数名 - わだばLisperになる

自分の好きな話題なのでトラックバックを打たせてもらいます!

確かに、古来のLispから引き継がれた変な名前の関数名は結構ありますよね。

そこで自分の分かる範囲で調べてみたことを書いてみたいと思います。

  • SETQのQ

これは、(set (quote foo))が縮まったもののようです。

qで終る系統は、quoteの略と、eqのqの系統があるようでeqの系統は、Common Lispでは滅びましたが、SRFI-1では復活したりしています。memqとか。

また、INTERLISP系にはquoteのq系統が沢山あるのですが、Maclisp系統にはそんなにないようです。

  • SETのF

これは、Kent Pitman氏によれば、"set field"の略だそうです。

onjoさんのLispy Days経由、ClikiのKent Pitman氏のcomp.lang.lispのポストであらましが読めます。

また、The Evolution of Lispによれば、これはPeter Deutsch氏のアイディアだそうで、当初setfqだったものが、Lispマシンでsetfになったとのこと。

リーダーで読み出した場所に値をセットするというアイディア自体は、Deutsch氏によれば、かの有名なアラン・ケイだそうです。

  • PRINCのC

これは、調べてみても解説がみつかりませんでした。princが一番最初に登場するのは、自分が調べた限りではPDP-6 LISP(AIM-116a)なのですが、どうも、characterのcなんじゃないかという感じです。PDP-6 LISPでは、print、prin1とprincの違いは、Common Lispでもそうですが、read入力にかなった文字列を出力するかどうか、とのことですが、princは、文字通りそのまま印字するということなので…。print、prin1では、特殊文字は/によってエスケープ処理して出力されます。

  • prin1の1

そもそもprin1の1は謎なのですが、自分が調べた限りでは、PDP-1 LISPに登場するのが最初のようです。printとの違いは、前後にスペースを出力したりしない、とのこと。もしかしたら、後述の名前の後の1系の補助関数的ネーミングなのかもしれません。

  • NCONC、RPLACA

mokeheheさんのお察しのとおりで、破壊的操作系の、n〜は、no consingで、rplacaは、replace carのようです。

ちなみに、LISP 1.5には、conc(恐らくconcatenateの略)という今のappendと同じ働きをするものが存在していました。当時APPENDは、引数を2つしか取らなかったためと思われます。PDP-6 LISPで、APPENDが拡張されたためか消滅してしまいました。

おまけ

  • mapcar、maplist

大元のLISP 1.5には、MAP、MAPLIST、MAPCONとあるのですが、MAPは、'(foo bar baz)というリストがあった場合に、'(foo bar baz)→'(bar baz)→'(baz)というようにリストを処理するもので、返り値には期待しない処理に使うものだったようです。(Common Lispでの、mapl)

このMAPを規準にして考えると、各要素をCARで処理して結果をリストで返せば、MAPCAR、LISTで処理すればMAPLIST、継げれば(CONcatenate)、MAPCONということなんじゃないかと思います。また、引数の[関数 リスト]という今日のCommon Lisp、Schemeでお馴染みの順番は、PDP-6 LISPからのようです。LISP 1.5、PDP-1 LISPまでは逆でした。(INTERLISPUtilispでも逆です。)

  • 名前の後の1

foo-bar1のような名前も良くみかけますが、これは、PDP-1 LISP位からの伝統のようで、foo-barの補助関数という意味で付けられることが多いようです。似たところでは、foo-bar-1、foo-bar-aux、foo-bar*等。引数を一つとるという意味で、Gaucheのlet1などもありますね。

以上、殆ど憶測の域を出なかったりするのですが、AIメモ等を読んだりして調べてみたところでした。

last.fmと連携するなにかを作りたい: 執着篇

| 00:21 | last.fmと連携するなにかを作りたい: 執着篇 - わだばLisperになる を含むブックマーク はてなブックマーク - last.fmと連携するなにかを作りたい: 執着篇 - わだばLisperになる

cl-audioscrobblerをみつけたので、もう自作する必要はないのですが、ちゃんと機能するクライアントをみつけたということもあり、自作のものは一体どの辺がおかしくて認証を通らなかったのかを確かめてみることにしました。

結論からいうと、ケアレスミスで、 md5sum-sequenceが返す#(1 2 3 255 255)のようなベクタを"010203ffff"のような文字列に変換する際に、0でパディングするのを忘れて、"123ffff"としていた、というものでした。なるほど、そりゃ駄目ですわな…。

修正したら自作のものもポストできるようになりました。とりあえず、すっきりした…。

(require :url-rewrite)
(require :drakma)
(require :md5)

(defpackage :last.fm
  (:use #:cl #:drakma #:url-rewrite))

(in-package :last.fm)

(defclass user ()
  ((name :initarg :name :accessor name :initform "")
   (password :initarg :password :accessor password :initform "")))

(defun make-get-scrobbler-uri-string (clientid clientver user)
  (let ((base "http://post.audioscrobbler.com/?hs=true&p=1.1"))
    (concatenate 'string base 
                 "&c=" clientid
                 "&v=" clientver
                 "&u=" user)))

(defun handshake-one (clientid clientver user)
  (http-request 
   (make-get-scrobbler-uri-string clientid clientver user)))
   
(defun decode-handshake-one (clientid clientver user)
  (let ((response 
         (http-request (make-get-scrobbler-uri-string clientid clientver user))))
    (destructuring-bind (uptodatep md5-challenge post-url interval) (ppcre:split "\\n" response)
      (list (string-equal "uptodate" uptodatep)
            md5-challenge
            post-url
            (ppcre:register-groups-bind (wait) ("INTERVAL ([0-9]+)" interval)
              (values (parse-integer wait :junk-allowed 'T)))
            user))))

(defun string-to-md5-string (str)
  (string-downcase 
   (apply #'concatenate 'string
          (map 'list (lambda (x) (format nil "~2,'0,X" x))
               (md5:md5sum-sequence str)))))

(defun make-md5-response (password md5-challange)
  (string-to-md5-string
   (concatenate 'string (string-to-md5-string password) md5-challange)))

(defun current-time-string ()
  (multiple-value-bind (s m h d mo y) (decode-universal-time (get-universal-time) 0)
    (format nil "~D-~2,'0D-~2,'0D ~2,'0D:~2,'0D:~2,'0D" y mo d h m s)))

(defmethod make-submit-uri ((user user) (artist string) (track string) (album string) (length integer))
  (destructuring-bind (uptodatep md5 post-url interval username)
      (decode-handshake-one "tst" "1.0" (name user))
    (declare (ignore uptodatep))
    (values 
     (concatenate 'string 
                  post-url
                  "?u=" username
                  "&s=" (make-md5-response (password user) md5)
                  "&" (url-encode "a[0]") "=" (url-encode artist)
                  "&" (url-encode "b[0]") "=" (url-encode album)
                  "&" (url-encode "t[0]") "=" (url-encode track)
                  "&" (url-encode "m[0]") "=" ;mbid
                  "&" (url-encode "l[0]") "=" (prin1-to-string length)
                  "&" (url-encode "i[0]") "=" (url-encode (current-time-string)))
     interval)))

(defun scrobble-current-song (user &key artist track album length)
  (multiple-value-bind (uri wait)
      (make-submit-uri user
                       artist
                       track
                       album
                       length)
    (sleep wait)
    (http-request uri)))

;; テスト
(setq me (make-instance 'user :name "user" :password "password"))

(print (scrobble-current-song 
        me
	:artist "Bonnie Pink"
	:track "Private Laughter"
	:album "Even So"
	:length 179))

cl-audioscrobbler

| 00:09 | cl-audioscrobbler - わだばLisperになる を含むブックマーク はてなブックマーク - cl-audioscrobbler - わだばLisperになる

今回は、cl-audioscrobblerを試してみます。

これは、last.fmに曲情報をポストしたりする、Audioscrobblerと連携するパッケージです。

この前私はlast.fmに曲情報をポストするコードを書いて認証が通らず頓挫したりしましたが、そんな私も一応作る前にClikiを調べて、last.fm関連のものが無いかは確認してみたつもりでした。これを発見したときには、なんだ、そのものズバリがあるんじゃないかよ!、と思ってしまいました。

Clikiの検索では、存外、目的のパッケージが見付けられないことが多い気がします。

この前も、AllegroのHTMLパーザを移植してClikiに公開した人が、「それ、もう移植されてるよ」と指摘される、なんてことがありました。

ちなみに、私もClikiでpxmlutilsを発見できずに、Allegroのオープンソース版をSBCLに移植した後で発見するという、全く同じ体験をしました。

移植ははちょっと直せば良いので簡単ではあるのですが、同じことをしてる人が他にも沢山いるような気がしてなりません(笑)

pxmlutilsっていう名前が良くないと思うなあ。

パッケージ名cl-audioscrobbler
本拠地サイトcl-audioscrobbler
ClikiCLiki: cl-audioscrobbler
ASDF-INSTALL

インストール

(asdf-install:install :cl-audioscrobbler)一発です。

試してみる


(require :cl-audioscrobbler)

;; クライアント作成
(defparameter *c*
  (cl-audioscrobbler::make-client "user" "password" "tst" "1.0"))

;; 曲情報をポスト
(cl-audioscrobbler::post-song *c* :1.1
			      "Bonnie Pink"
			      "Even So"
			      "Private Laughter"
			      "179"
			      "1")

という感じで曲情報がポストできます。

プロジェクトのサイトには非常に丁寧に作られたドキュメントが沢山用意されていて非常に親切です。

ゲスト



トラックバック - http://cadr.g.hatena.ne.jp/g000001/20080116