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 |

2007-10-28


DrakmaでTwitterに投稿

| 20:00 | DrakmaでTwitterに投稿 - わだばLisperになる を含むブックマーク はてなブックマーク - DrakmaでTwitterに投稿 - わだばLisperになる

Drakma(Common Lispで書かれたウェブクライアント)を使ったことがなかったので、これを使って何かしてみたいと思いTwitterに与えられた文字列を投稿する関数を書いてみました。

本当は、自分が利用している図書館の本の予約状況を取得するようなものを作りたかったんですが、日本語を扱っているページでは、UTF-8以外のページのクッキーの取得が上手く行かず*1、自力では解決できなかったので、UTF-8でできているTwitterで何かすることに方向転換しました。

UTF-8のページだと、殆どDrakmaのチュートリアルの通りですんなりとできました。

本当は、パスワード等は、別ファイルに書き出して読み込ませる方が良いと思いますが直に書いてます。

Drakmaは思った以上に便利なんですが、どうやったら文字コードの問題がクリアできるのかー。

(defun update-twitter-status (mesg)
  "twitterに投稿する"
  (let ((mesg-list (split-by-length mesg 50))
	(cj (make-instance 'drakma:cookie-jar)))
    ;; login
    (drakma:http-request "http://twitter.com/sessions" 
			 :external-format-in :utf-8 
			 :external-format-out :utf-8
			 :method :post
			 :cookie-jar cj
			 :parameters `(("username_or_email" . "おなまえ") 
				       ("password" . "パスワード")))
    ;; update
    (do ((m mesg-list (cdr m)))
	((endp m) (length mesg))
      (drakma:http-request "http://twitter.com/status/update" 
			   :external-format-in :utf-8
			   :external-format-out :utf-8
			   :method :post
			   :cookie-jar cj
			   :parameters `(("status" . ,(car m))))
      (unless (endp (cdr m)) (sleep 5)))))

(defun split-by-length (str len)
  "指定した長さ`len'で文字列`str'を区切り、結果を文字列のリストにして返す。"
  (let ((slen (length str)))
    (if (> slen len)
	(do ((pos len (+ pos len))
	     res)
	    ((> pos slen) 
	     (nreverse (push (subseq str (- pos len) slen) res)))
	  (push (subseq str (- pos len) pos) res))
	`(,str))))

Alexandria (1)

| 01:21 | Alexandria (1) - わだばLisperになる を含むブックマーク はてなブックマーク - Alexandria (1) - わだばLisperになる

PG氏の余り物ユーティリティを読み終ったので、次は何にしようかと悩みましたが、とりあえず、定番ユーティリティ集の座を狙っているような、alexandriaのコードを読んでみることにしました。

名前からして、立派な図書館であったAlexandria図書館のようなライブラリを目指しているのであろうということは何となく分かります。

とりあえず、適当にぽつぽつと拾い読みしてみたいと思っています。

Alexandriaのページ:Alexandria

asdf-installも可能なようですが、プロジェクトの人が準備したものではないようです。

とりあえず自分は、公式ページの通りdarcsで取得して、手動でasdfに登録しました。

お題

features

暗記で再現

;--- features.lisp
(defun featurep (feature-expression)
  (etypecase feature-expression
    (symbol (not (null (member feature-expression *features*))))
    (cons   (ecase (first feature-expression)
	      (:and (every #'featurep (rest feature-expression)))
	      (:or  (some  #'featurep (rest feature-expression)))
	      (:not (not (featurep (second feature-expression))))))))

できた。carとcdrを使わないのに、cadrを使うのは謎なのでsecondにしてみた。

Emacs Lispではお馴染で、Emacs上でコードを編集しているとハイライト表示もされるしCommon Lisp標準の機能かと思いきや、標準ではなかったりするfeaturep。

後期Maclispにはあるようなので、その流れでEmacsにもあるのかもしれません。

これはCLRFIの1番で定義されているfeaturepとまったく同じコードなんですが、CLRFIとも関係あるのでしょうか。

;; 動作
(featurep :cffi)
;=> t
(featurep '(:not :cffi))
;=> nil
(featurep '(:and :sbcl :x86 :linux))
;=> t

お題

clamp

暗記で再現

;--- numbers.lisp
(declaim (inline clamp))
(defun clamp (number min max)
  (if (< number min)
      min
      (if (> number max)
	  max
	  number)))

できた。上限と下限を設定して、はみ出したものは上限か下限の値を返すというものらしい。

自分は何となく

(defun clamp (number min max)
  (cond ((< number min) min)
	((> number max) max)
	('T number)))

と書きたい派。

;; 動作
(clamp 101 1 100)
;=> 100

お題

iota

暗記で再現

;--- numbers.lisp
(declaim (inline iota))
(defun iota (n &key (start 0) (step 1))
  (declare (type (integer 0) n) (number start stop))
  (loop :repeat n 
        :for i = (+ start (- step step)) :then (+ i step)
        :collect i))

できた。これはおなじみSRFIのiota。しかし、startや、stepをキーワード引数として取るようにしているところが違う。

;; 動作
(iota 10 :start 1.5 :step 2)
;=> (1.5 3.5 5.5 7.5 9.5 11.5 13.5 15.5 17.5 19.5)

お題

map-iota

暗記で再現

;--- numbers.lisp
(declaim (inline map-iota))
(defun map-iota (n fn &key (start 0) (step 1))
  (declare (type (integer 0) n) (number start step))
  (loop :repeat n
        :for i = (+ start (- step step)) :then (+ i step)
        :do (funcall fn i))
  n)

できた。iotaの結果の各要素に関数を適用するという感じ。

PG氏のmap-intに非常に近いような気もするけれど、返り値は、結果のリストではなくて、引数のnを返したりするところが違う。

;; 動作
(map-iota #'princ 5 :start 1 :step 2)
->13579
;; 参考 PG氏のmap-int
(defun map-int (func n)
  "call FUNC on integers from 0 through N - 1, returning a list of the results."
  (let ((acc '()))
    (dotimes (i n)
      (push (funcall func i)
	    acc))
    (nreverse acc)))

雑感

今のところこのライブラリに含まれるマクロや関数の由来を記したドキュメントの類が全然ないんですが、手持ちの駒の重複を把握するためにもあると便利だなと感じました。

*1::external-format-inで、:euc-jpの扱いが良く分からず、:force-binary tで読み込んで、octets-to-stringで戻すことはできるけれど、それだとcookieは拾ってくれない、などとぐるぐる悩む