#:g1: frontpage

 

cl-rssの紹介

Posted 2014-04-17 16:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の108日目です。

cl-rssとはなにか

 cl-rssは、Kevin M. Rosenberg氏作のRSS 2.0をパーズしてCLOSのオブジェクトにしてくれるライブラリです。

パッケージ情報

パッケージ名cl-rss
Quicklisp
参考サイト
CLiKihttp://cliki.net/cl-rss
Quickdocshttp://quickdocs.org/cl-rss

インストール方法

(ql:quickload :rss)

試してみる

 どんな関数があるかは、Quickdocsで確認できます。

 ライブラリにはサンプル的にrss:show-sitesが定義されているので、この辺りをいじってみると使い方が分かります。
rss:show-sitesだと、タイトルのみなので、リンクのURLも表示するように改造してみます。
rss:rss-itemは

(*:slot-names (find-class 'rss-item))
;=>  (TITLE LINK DESCRIPTION PUB-DATE)

のような感じになっています。

(defun show-sites/ (&optional (sites *sites*))
  (dolist (site (mklist sites))
    (awhen (rss-site site)
           (display-site/ it))))


(defun display-site/ (site &key (stream *standard-output*))
  (format stream "Site: ~A~%" (title site))
  (dolist (item (items site))
    (format stream "  ~A~%~4T~A~2%" (title item) (link item))))


(show-sites/ '("http://www.reddit.com/r/lisp/.rss"))
;>>  Site: Lisp
;>>    Fear of Macros
;>>      http://www.reddit.com/r/lisp/comments/239ee3/fear_of_macros/
;>>  
;>>    Dylan 2016: Evolving Dylan
;>>      http://www.reddit.com/r/lisp/comments/239r8i/dylan_2016_evolving_dylan/
;>>  
;>>    {} descriptions is a meta level descriptions library for Common Lisp.
;>>      http://www.reddit.com/r/lisp/comments/238zj2/descriptions_is_a_meta_level_descriptions_library/
;>>  
;>>    Noobtuts - Two Clojure Math Tutorials
;>>      http://www.reddit.com/r/lisp/comments/239j9o/noobtuts_two_clojure_math_tutorials/
;>>  
;>>    The Fate of "The ANSI Common Lisp Reference Book"
;>>      http://www.reddit.com/r/lisp/comments/236xta/the_fate_of_the_ansi_common_lisp_reference_book/
;>>  
;>>    Common Lisp implemented in Emacs Lisp
;>>      http://www.reddit.com/r/lisp/comments/235uii/common_lisp_implemented_in_emacs_lisp/
;>>  
;>>    Babel2
;>>      http://www.reddit.com/r/lisp/comments/233mkx/babel2/
;>>  
;>>    The Paren Programming Language now supports threads.
;>>      http://www.reddit.com/r/lisp/comments/233d3t/the_paren_programming_language_now_supports/
;>>  
;>>    Nullable objects in Common Lisp?
;>>      http://www.reddit.com/r/lisp/comments/22xn03/nullable_objects_in_common_lisp/
;>>  
;>>    OSX GUI tutorial
;>>      http://www.reddit.com/r/lisp/comments/22wwko/osx_gui_tutorial/
;>>  
;>>    Strange sbcl/cffi behaviour
;>>      http://www.reddit.com/r/lisp/comments/22wywo/strange_sbclcffi_behaviour/
;>>  
;>>    Puppet Labs move to Clojure
;>>      http://www.reddit.com/r/lisp/comments/22wdct/puppet_labs_move_to_clojure/
;>>  
;>>    Meagan Waller - Conditional binding in Clojure
;>>      http://www.reddit.com/r/lisp/comments/22ts2k/meagan_waller_conditional_binding_in_clojure/
;>>  
;>>    Interview with Stuart Halloway, author of 'Programming Clojure'
;>>      http://www.reddit.com/r/lisp/comments/22om7e/interview_with_stuart_halloway_author_of/
;>>  
;>>    Whatever became of CLIM?
;>>      http://www.reddit.com/r/lisp/comments/22lbpe/whatever_became_of_clim/
;>>  
;>>    Lisp interface library: video presentation
;>>      http://www.reddit.com/r/lisp/comments/22i9v7/lisp_interface_library_video_presentation/
;>>  
;>>    Clojure Cookbook has arrived
;>>      http://www.reddit.com/r/lisp/comments/22a1q3/clojure_cookbook_has_arrived/
;>>  
;>>    Cache friendly memory management?
;>>      http://www.reddit.com/r/lisp/comments/2283i0/cache_friendly_memory_management/
;>>  
;>>    Octopus
;>>      http://www.reddit.com/r/lisp/comments/22710w/octopus/
;>>  
;>>    Lisp Aha! moments
;>>      http://www.reddit.com/r/lisp/comments/2235wt/lisp_aha_moments/
;>>  
;>>    SLIME User Manual version 2.5 (PDF)
;>>      http://www.reddit.com/r/lisp/comments/2235zh/slime_user_manual_version_25_pdf/
;>>  
;>>    SBCL Release Versions
;>>      http://www.reddit.com/r/lisp/comments/2242jf/sbcl_release_versions/
;>>  
;>>    Hashtable variant of (describe)
;>>      http://www.reddit.com/r/lisp/comments/224oo2/hashtable_variant_of_describe/
;>>  
;>>    Real World Clojure
;>>      http://www.reddit.com/r/lisp/comments/222pl9/real_world_clojure/
;>>  
;>>    Wasn't there something about indentation tuning with Slime recently?
;>>      http://www.reddit.com/r/lisp/comments/220ehs/wasnt_there_something_about_indentation_tuning/
;>>  
;>>  
;=>  NIL

 ちなみに、parse-rss-streamの中のparse-channel-childがコケてrss-parse-errorを上げますが、今回はCL:IGNORE-ERRORSで囲んでスルーします。

(defun parse-rss-stream
  ...
  (map nil (lambda (child) 
             (ignore-errors
               (parse-channel-child child rss strict?)))
       (xmls:xmlrep-children channel))
  ...)

また、処理系によって、net.aserve.client:do-http-requestの文字化けが良く分からないという場合は、drakma:http-requestに差し替えるのも手かもしれません。

まとめ

 今回は、cl-rssを紹介してみました。
ライブラリを修正するより自作した方が早いという人もいるかもしれません。

sloopの紹介

Posted 2014-04-16 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の107日目です。

sloopとはなにか

 sloopは、William Schelter氏作が1985年頃に作製した繰り返しマクロのライブラリです。
基本的な機能はMITのLOOP互換になっています。

パッケージ情報

パッケージ名sloop
参考サイトPackage: lang/lisp/code/iter/loop/sloop/

インストール方法

 上記CMUのAIレポジトリからソースをダウンロードして動かしてみましょう。
AIレポジトリのソースは改変禁止と書いてありますが、GCLのソースはGPLなので改変して再配布する際にはGCLのものが良いかと思います〈GCL版は若干の修正がされています〉

試してみる

 1984年の最初のCommon Lispでは、LOOPは単純な無限ループの機能のみとなっていました。
現在ANSI Common Lispに含まれているLOOPの源流のMIT系LispマシンのLOOPは、1980年位からLispマシン上で利用されていて、一定の支持は集めていたようですが、Common Lispにそのまま導入するかどうかはCLtL1の段階では見送られたというところでした。

 CLtL1にリッチな繰り返し構文が含まれなかったお蔭で1980年代後半に結局Lispマシン系のLOOPがCommon Lispに採用されるまでの間に、色々な繰り返し構文や、LOOP互換構文が登場しました。
sloopもそんなものの一つで、CLtL1なKCLやAKCLで専ら利用されたようです。
William Schelter氏は、AKCLの開発者だったようで、AKCL〜GCLでも結構な量のコードがsloopを利用して記述されていたりします。

 基本的な機能はANSI Common LispのLOOPと同様です。

(let ((lis '(1 3 4 2 1 6 7 3 0 22)))
  (sloop :for (i a) :on lis :by 'cddr
         :when (oddp i)
         :collecting i
         :else
         :append (sloop :for j :below a :collecting j)))
;=>  (1 0 1 1 7 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21)


(let ((n 5))
  (sloop :for i :below n
	 :for a :below (* 2 n)
         :unless (oddp i)
         :sum i
         :else
         :sum (sloop :for j :below a :sum j)))
;=>  9

(let ((lis '(1 3 4 2 1 6 7 3 0 22)))
  (sloop :for (i a) :on lis :by 'cddr
         :when (oddp i)
         :sum i
         :and :count i
         :else
         :sum
         (sloop :for j :below a :sum j)))
;=>  244


(let ((lis '(1 3 4 2 1 6 7 3 0 22)))
  (sloop for (a i) on lis by 'cddr
         when (not (zerop a))
         nconc (list (* 2 a) i)
         else nconc (list 3 i)
         while (not (eql i 6))))
;=>  (2 3 8 2 2 6)


(let ((lis '(1 3 4 2 1 6 7 3 0 22)))
  (sloop for (a i) on lis by 'cddr
         when (not (zerop a))
         nconc (list (* 2 a) i) into tem
         else nconc (list 3 i) into tel
         finally (loop-return (append tem tel))))
;=>  (2 3 8 2 2 6 14 3 3 22)

 以上のように基本的なところは同じですが、パッケージや、ハッシュテーブル等の利用では少し書き方が違ってきます。

(let ((table (make-hash-table)))
  (setf (gethash 3 table) 11)
  (setf (gethash 11 table) 7)
  (sloop for (key elt) in-table table sum elt into tot sum key into keys
	 finally (loop-return (list keys tot))))
;=>  (14 18)


(sloop :for sym in-package :cl
       :when (eql sym 'cons) :do (loop-return sym))
;=>  CONS

in-packageや、in-tableで指定します。ANSI CLのLOOPより分かりやすい気もしないでもありません。

(sloop :for i :from 0 :to 99
       :declare (fixnum i)
       :sum i)
;=>  4950

さらに型宣言はdeclareキーワードで指定します。

 加えて独自の拡張機能があります。

sloop
(sloop :for i :below 5
       sloop (for j  :to i :collecting (list i j)))
;=>  ((0 0) (1 0) (1 1) (2 0) (2 1) (2 2) (3 0) (3 1) (3 2) (3 3) (4 0) (4 1) (4 2) (4 3) (4 4))

入れ子にする際に(sloop ... (sloop forではなく、(sloop ... sloop (forと書けるようにするもの。すっきりするようなしないような。

in-carefully
(sloop for e in-carefully '(1 2 3 . 4) collect e)
;=>  (1 2 3)

NIL終端でないリストは終端を無視して扱うという指定

in-fringe
(sloop :for x in-fringe '(1 2 (3 (4 5) . *) 8 1 2)
       :collect x)
;=>  (1 2 3 4 5 * 8 1 2)

リストをflattenしてくれるもの

averaging
(sloop :for e :from 1 :to 99 :averaging e)
;=>  50.0

平均を算出

collate
(sloop for v in-fringe '(1  (7 3 (2 . 2) 9 (4 11)) 5 . 3)
       when (oddp v)
       collate v)
;=>  (1 3 5 7 9 11)
(sloop repeat 15 collate (random 2))
;=>  (0 1)

昇順にソートしつつ重複も削除するcollect

 ユーザーも定義することが可能でsloop:def-loop-collect、sloop:def-loop-map、 sloop:def-loop-forあたりで定義が可能です。上記の拡張キーワードはこれらで定義されているので独自に定義する場合には参考になると思います。

まとめ

 今回は、sloopを紹介してみました。
GCLのソースを眺めていて、SLOOPという見慣れない物が大量に使われているのを発見したので紹介してみました。

eggs: progress-indicatorsの紹介

Posted 2014-04-15 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の106日目です。

eggs: progress-indicatorsとはなにか

 eggs: progress-indicatorsは、Chickenのターミナル上にプログレスバーを表示するライブラリです。

パッケージ情報

パッケージ名eggs: progress-indicators
ドキュメントprogress-indicators - The Chicken Scheme wiki

インストール方法

 chicken-installを利用して

sudo chicken-install progress-indicators

とでもしてあれば、

(use progress-indicators)

で利用できます。

 どんな関数があるかは、ドキュメントサイトから確認できますが、プログレスバーを表示する関数と、くるくる回転するスピナーを表示する関数の2つが主です。
Gaucheのtext.progressでは、表示用のクロージャーを生成する方式でしたが、eggs: progress-indicatorsでは、プログレスバーのオブジェクト〈構造体〉を表示用の関数が表示する、という作りになっています。

(use progress-indicators)
(use srfi-42)
(use srfi-18)


(let ((bar (make-progress-bar #:max 256)))
  (do-ec (: i 256)
    (begin
      (show-progress-bar bar)
      (advance-progress-bar! bar)
      (thread-sleep! 0.1)))
  (newline))
;>> [256/256=====================================================>|  100%]
(let ((bar (make-progress-bar #:max 256 #:end-message "完")))
  (do-ec (: i 256)
    (begin
      (show-progress-bar bar)
      (advance-progress-bar! bar)
      (thread-sleep! 0.1)))
  (finish-progress-bar! bar)
  (newline))
;>> [256/256======================================================|完]

finish-progress-bar!を利用すると完了時のメッセージを表示させ終了させます。

 スピナーの方も、


(let ((s (make-spinner)))
  (do-ec (: i 25600)
    (begin
     (advance-spinner! s)
     (thread-sleep! 0.1)))
  (finish-spinner! s)
  (newline))
;>> / 

のようにして利用できます。
また、プログレスバーと組み合わせての利用も可能です。

(let ((s (make-spinner))
      (bar (make-progress-bar #:max 256 #:end-message "完")))
  (do-ec (: i 256)
    (begin
      (show-progress-bar bar)
      (advance-progress-bar! bar)
      (advance-spinner! s)
      (thread-sleep! 0.1)))
  (finish-progress-bar! bar)
  (finish-spinner! s)
  (newline))
;>> [[256/256======================================================|完]100%/

まとめ

 今回は、eggs: progress-indicatorsを紹介してみました。
シェルスクリプトで利用されることが少ない為か、Common Lispではこういうのが少ない気がします。Common Lispでもこういうのがあると良いですね。

text.progressの紹介

Posted 2014-04-14 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の105日目です。

text.progressとはなにか

 text.progressは、Gaucheでコンソールにプログレスバーを表示するためのライブラリです。

パッケージ情報

パッケージ名text.progress
GaucheマニュアルGauche ユーザリファレンス: 11.43 text.progress - テキスト端末上でプログレスを表示する

インストール方法

(use text.progress)

試してみる

 詳しくドキュメントが書かれているので眺めるだけで使い方は分かると思いますが、(make-text-progress-bar)が関数を生成するようになっていて、生成された関数を実行することでプログレスバーが描画されます。

(let ((bar (make-text-progress-bar)))
  (dotimes (i 100)
    (sys-nanosleep 10000000)
    (bar 'inc 1))
  (newline))

;>> progress      |########################################|  100/100  00:00 ETA
;=> #<undef>

描画の仕組みですが、バーを描画して復帰してまた描画して、の繰り返しで、

(begin 
  (dotimes (i 100)
    (sys-nanosleep 100000000)
    (display (make-string i #\#))
    (display (make-string (- 100 i) #space))
    (display ": ")
    (display i)
    (display "\r")
    (flush))
  (newline))

;>> ################################################################################################### : 99
;=> #<undef> 

のようなものが骨子です。

 バーの生成については、オプションが色々と取れるようになっていて、カスタマイズが簡単にできるようになっています。

(let ((bar (make-text-progress-bar :header "試験"
                                   :header-width 2
                                   :bar-char #\o
                                   :num-width 13
                                   :max-value 256)))
  (dotimes (i 256)
    (sys-nanosleep 10000000)
    (bar 'inc 1))
  (newline))

;>> 試験|oooooooooooooooooooooooooooooooooooooooo|      256/256  00:00 ETA
;=> #<undef>

まとめ

 今回は、text.progressを紹介してみました。
ちょっとしたスクリプトの作成でこういうのが欲しいことがありますが、手軽に利用できて良いですね。

cl-string-matchの紹介

Posted 2014-04-13 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の104日目です。

cl-string-matchとはなにか

 cl-string-matchは、Victor Anyakin氏作の文字列探索のライブラリです。

パッケージ情報

パッケージ名cl-string-match
Quicklisp
プロジェクトサイトcl-string-match | Free Development software downloads at SourceForge.net
CLiKihttp://cliki.net/cl-string-match
Quickdocshttp://quickdocs.org/cl-string-match

インストール方法

(ql:quickload :cl-string-match)

試してみる

 どんな関数があるかは、Quickdocsで確認できます。

 現在のところ

  • Brute-force
  • ボイヤー-ムーア法
  • Boyer-Moore-Horspool
  • ラビン-カープ法
  • クヌース-モリス-プラット法
  • エイホ-コラシック法
  • Ukkonen's suffix tree construction

がサポートされているようです。

(defvar *text* (*:read-file-to-string "/usr/share/dict/words"))


(search "lithographing" *text*)
;=>  548599


(sm:string-contains-ac "lithographing" *text*)
;=>  548599


(sm:string-contains-bm "lithographing" *text*)
;=>  548599


(sm:string-contains-rk "lithographing" *text*)
;=>  NIL


(sm:string-contains-bmh "lithographing" *text*)
;=>  NIL


(sm:string-contains-kmp "lithographing" *text*)
;=>  548599


(sm:string-contains-brute "lithographing" *text*)
;=>  548599




(let ((idx (sm:initialize-rk "list")))
  (sm:search-rk idx *text*))
;=>  NIL


(let ((idx (sm:initialize-ac "list")))
  (sm:search-ac idx *text*))
;=>  3365
;    0


(let ((idx (sm:initialize-bm "list")))
  (sm:search-bm idx *text*))
;=>  3365


(let ((idx (sm:initialize-bmh "list")))
  (sm:search-bmh idx *text*))
;=>  21736


(let ((idx (sm:initialize-kmp "list")))
  (sm:search-kmp idx *text*))
;=>  3365

bmhとrkの結果がどういうことなのかについては置いておいて、速度等はどうなのかCL:SEARCHとでも比較してみます〈bmhとrkは除外〉

(defmacro ss-bench (pat text &optional (times 100))
  `(progn 
     ,@(mapcar (lambda (x)
                 (let ((xpr `(time 
                              (dotimes (i ,times)
                                (,x ,pat ,text)))))
                   `(progn
                      (pprint ',xpr)
                      ,xpr)))
               '(search 
                 sm:string-contains-ac
                 sm:string-contains-bm
                 ;; sm:string-contains-rk
                 ;; sm:string-contains-bmh
                 sm:string-contains-kmp
                 sm:string-contains-brute))))
(ss-bench "lithographing" *text*)
;>> (TIME (DOTIMES (I 100) (SEARCH "lithographing" *TEXT*)))
;>> Evaluation took:
;>>   1.546 seconds of real time
;>>   1.544096 seconds of total run time (1.544096 user, 0.000000 system)
;>>   99.87% CPU
;>>   3,700,604,277 processor cycles
;>>   0 bytes consed
;>>   
;>> 
;>> (TIME (DOTIMES (I 100) (SM:STRING-CONTAINS-AC "lithographing" *TEXT*)))
;>> Evaluation took:
;>>   4.300 seconds of real time
;>>   4.272267 seconds of total run time (4.272267 user, 0.000000 system)
;>>   99.35% CPU
;>>   10,293,248,214 processor cycles
;>>   1,694,576 bytes consed
;>>   
;>> 
;>> (TIME (DOTIMES (I 100) (SM:STRING-CONTAINS-BM "lithographing" *TEXT*)))
;>> Evaluation took:
;>>   0.303 seconds of real time
;>>   0.304019 seconds of total run time (0.304019 user, 0.000000 system)
;>>   100.33% CPU
;>>   725,790,519 processor cycles
;>>   221,072 bytes consed
;>>   
;>> 
;>> (TIME (DOTIMES (I 100) (SM:STRING-CONTAINS-KMP "lithographing" *TEXT*)))
;>> Evaluation took:
;>>   0.467 seconds of real time
;>>   0.468029 seconds of total run time (0.468029 user, 0.000000 system)
;>>   100.21% CPU
;>>   1,118,114,415 processor cycles
;>>   32,704 bytes consed
;>>   
;>> 
;>> (TIME (DOTIMES (I 100) (SM:STRING-CONTAINS-BRUTE "lithographing" *TEXT*)))
;>> Evaluation took:
;>>   0.389 seconds of real time
;>>   0.388024 seconds of total run time (0.388024 user, 0.000000 system)
;>>   99.74% CPU
;>>   929,401,578 processor cycles
;>>   38,784 bytes consed

bm(ボイヤー-ムーア法)あたりは5倍程度速いようです。

まとめ

 今回は、cl-string-matchを紹介してみました。
プロジェクトページもドキュメントも綺麗にまとまっているので今後の発展に期待したいプロジェクトです。

cl-apiの紹介

Posted 2014-04-12 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の103日目です。

cl-apiとはなにか

 cl-apiは、Common Lispのドキュメント生成システムです。

パッケージ情報

パッケージ名cl-api
Quicklisp
CLiKihttp://cliki.net/cl-api
Quickdocshttp://quickdocs.org/cl-api

インストール方法

(ql:quickload :cl-api)

試してみる

 どんな関数があるかは、Quickdocsで確認できますが、関数はcl-api:api-genのみです。

 使い方は非常にシンプルで、

(cl-api:api-gen :common-lisp "/tmp/")

のように実行すると、common-lispパッケージのドキュメンテーションが/tmp/common-lisp.htmlという一つのHTMLファイルに書き出されます。

cl-api

 ちなみに、cl-api::doc-classがbuilt-in-classをfinalize-inheritanceしてしまいエラーとなる場合があるので、

(unless (class-finalized-p class) (finalize-inheritance class))

などとしておくと良いのかなと思います〈そもそもbuilt-in-classが来ることを想定してないかも〉。

まとめ

 今回は、cl-apiを紹介してみました。
自作のライブラリのドキュメンテーションの充実具合をさっと眺めるのには良いかなと思います。

roman.pltの紹介

Posted 2014-04-10 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の101日目です。

roman.pltとはなにか

 roman.plt整数とローマ数字の文字列表現を相互変換するRacketのライブラリです。

パッケージ情報

パッケージ名roman.plt
PLaneTPLaneT Package Repository : PLaneT > ams > roman.plt

インストール方法

 Racket内から

(require (planet ams/roman:1:1/roman))

でOKです。

試してみる

 どんな関数があるかは、上記のPLaneTのドキュメントで確認できます。
説明なしでも使い方は分かるかと思いますが、int->romanと、roman->intが主な関数です。

(int->roman 1121)
;=> "MCXXI"


(roman->int "MCXXI")
;=> 1121


(int->roman 3999)
;=> "MMMCMXCIX"


(int->roman 4000)
;!> int->roman: contract violation
;!> expected: (integer-in 1 3999)

3999より大きい数には対応していません。

 おまけ的に足し算、かけ算、割り算、余りの関数がラテン語名の関数で提供されています。

(apply summa (map int->roman (iota 10 1)))
;=> "LV"


(differentia "C" "LX")
;=> "XL"


(productum "I" "II" "III" "IV")
;=> "XXIV"


(quotiens "X" "III")
;=> "III"


(residuum "X" "III")
;=> "I"

まとめ

 今回は、roman.pltを紹介してみました。
MacLISPでは基数をローマ数字に設定できたり、MacLISP系LISPのFORMATでもローマ数字を出力できたり、何かと馴染み深いローマ数字ですが、MacLISP時代の実装から代々大抵は3999までのサポートです。
4000以上の表現には何か問題でもあるのでしょうか。

quicksearchの紹介

Posted 2014-04-09 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の100日目です。

quicksearchとはなにか

 quicksearchは、Takaya OCHIAI氏作のCommon Lispのライブラリを検索するユーティリティです。

パッケージ情報

パッケージ名quicksearch
Quicklisp
参考サイト
Quickdocshttp://quickdocs.org/quicksearch

インストール方法

(ql:quickload :quicksearch)

 手元で試したところではqs::extract-github-repos内でエラーになるので適当に修正しました。
どうもflexi-streams:octets-to-stringに文字列が来てしまうのが原因のようです。

(defun response-string (response)
  #+#:Error-2014-04-08
  ;; This sequence can't be decoded using UTF-8 as it is too short.
  ;;  2 octets missing at the end.
  (flexi-streams:octets-to-string response :external-format :utf-8)
  #-#:Error-2014-04-08
  (etypecase response
    (STRING response)
    (VECTOR 
     (flexi-streams:octets-to-string response :external-format :utf-8))))


;; github api-v3 search
(defun extract-github-repos (response)
  (let* ((jason (yason:parse (response-string response))))
    (loop :for repo :in (gethash "repositories" jason)
          :unless (gethash "fork" repo)   ;only master is displayed
            :collect (list (gethash "name" repo)
                           (gethash "url" repo)
                           (let ((desc (gethash "description" repo)))
                             (unless (string= "" desc)
                               desc))))))

試してみる

 どんな関数があるかは、Quickdocsで確認できます。

 使い方はシンプルで検索したいキーワードをquicksearchに渡すだけです。

(quicksearch:quicksearch "srfi")
;>>  
;>>  SEARCH-RESULTS: "srfi"
;>>  
;>>   Cliki
;>>    SRFI
;>>    cl-op
;>>    Riastradh's Lisp Style Rules [for Common Lisp]
;>>  
;>>   GitHub
;>>    srfi
;>>    srfi-19
;>>    srfi-99
;>>    srfi-28
;>>    srfi-23
;>>    srfi-87
;>>    srfi-13
;>>    srfi-74
;>>    srfi-89
;>>    srfi-25
;>>    srfi-64
;>>    srfi-42
;>>    srfi-97
;>>    srfi-61
;>>    srfi-60
;>>    srfi-106
;>>    srfi-66
;>>    srfi-101
;>>    srfi-17
;>>    srfi-51
;>>    srfi-35
;>>    srfi-6
;>>    srfi-43
;>>    srfi-0
;>>    srfi-10
;>>    srfi-40
;>>    srfi-45
;>>    srfi-27
;>>    srfi-9
;>>    srfi-4
;>>    srfi-90
;>>    srfi-31
;>>    srfi-78
;>>    srfi-compat
;>>    srfi-34
;>>    srfi-94
;>>    srfi-112
;>>    srfi-16
;>>    srfi-55
;>>    srfi-63
;>>    srfi-98
;>>    srfi-29
;>>    srfi-67
;>>    srfi-38
;>>    srfi-11
;>>    srfi-18
;>>    srfi-57
;>>    srfi-26
;>>    srfi-95
;>>    srfi-37
;>>    .......> 35
;>>  
;=>  CL:T

 REPLで利用することを想定しているのだと思いますが、qs:?でより短く書くことも可能です。
検索する対象も選択できますが、:gでgithub、:bでbitbucket、:cがCLiKi、:qがQuicklispです。:uで検索結果のURLを表示します。

(qs:? "clim" :u)
;>>  
;>>  SEARCH-RESULTS: "clim"
;>>  ======================
;>>  
;>>   Quicklisp
;>>   ---------
;>>    automaton
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/Drei/cl-automaton/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    clim
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    clim-basic
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    clim-clx
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    clim-core
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    clim-examples
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    clim-gtkairo
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    clim-lisp
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    clim-listener
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    clim-looks
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    clim-null
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    clim-postscript
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    climacs
;>>        ~/quicklisp/dists/quicklisp/software/climacs-20101006-cvs/
;>>        http://beta.quicklisp.org/archive/climacs/2010-10-06/climacs-20101006-cvs.tgz
;>>    climc
;>>        http://beta.quicklisp.org/archive/climc/2014-03-16/climc-20140316-git.tgz
;>>    climc-test
;>>        http://beta.quicklisp.org/archive/climc/2014-03-16/climc-20140316-git.tgz
;>>    climon
;>>        http://beta.quicklisp.org/archive/climon/2014-03-16/climon-20140316-git.tgz
;>>    climon-test
;>>        http://beta.quicklisp.org/archive/climon/2014-03-16/climon-20140316-git.tgz
;>>    clouseau
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    conditional-commands
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/Extensions/conditional-commands/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    drei-mcclim
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    drei-tests
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    esa
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/ESA/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    esa-mcclim
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    functional-geometry
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/Apps/Functional-Geometry/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    goatee-core
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    mcclim
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    mcclim-gif-bitmaps
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    mcclim-jpeg-bitmaps
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    mcclim-png-bitmaps
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    mcclim-tiff-bitmaps
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>    mcclim-tree-with-cross-edges
;>>        ~/quicklisp/dists/quicklisp/software/mcclim-20140316-git/Experimental/tree-with-cross-edges/
;>>        http://beta.quicklisp.org/archive/mcclim/2014-03-16/mcclim-20140316-git.tgz
;>>  
;>>   Cliki
;>>   -----
;>>    CLIM
;>>        http://www.cliki.net/CLIM
;>>    Climc
;>>        http://www.cliki.net/Climc
;>>    climacs
;>>        http://www.cliki.net/climacs
;>>    clim-chess
;>>        http://www.cliki.net/clim-chess
;>>    clim-desktop
;>>        http://www.cliki.net/clim-desktop
;>>    McCLIM
;>>        http://www.cliki.net/McCLIM
;>>    Alpine
;>>        http://www.cliki.net/Alpine
;>>    beirc
;>>        http://www.cliki.net/beirc
;>>    CL-Emacs
;>>        http://www.cliki.net/CL-Emacs
;>>    cl-menusystem
;>>        http://www.cliki.net/cl-menusystem
;>>    cl-reversi
;>>        http://www.cliki.net/cl-reversi
;>>    clones
;>>        http://www.cliki.net/clones
;>>    Closure
;>>        http://www.cliki.net/Closure
;>>    Craig Lanning
;>>        http://www.cliki.net/Craig%20Lanning
;>>    Cyrus Harmon
;>>        http://www.cliki.net/Cyrus%20Harmon
;>>    de.setf.graphics
;>>        http://www.cliki.net/de.setf.graphics
;>>    decaf
;>>        http://www.cliki.net/decaf
;>>    Development
;>>        http://www.cliki.net/Development
;>>    Dwight Holman
;>>        http://www.cliki.net/Dwight%20Holman
;>>    Emacs
;>>        http://www.cliki.net/Emacs
;>>    Ernestine
;>>        http://www.cliki.net/Ernestine
;>>    esa
;>>        http://www.cliki.net/esa
;>>    Express Engine
;>>        http://www.cliki.net/Express%20Engine
;>>    Extension webactions
;>>        http://www.cliki.net/Extension%20webactions
;>>    Features
;>>        http://www.cliki.net/Features
;>>    floyd-warshall
;>>        http://www.cliki.net/floyd-warshall
;>>    Gsharp
;>>        http://www.cliki.net/Gsharp
;>>    ICanCAD
;>>        http://www.cliki.net/ICanCAD
;>>    Jochen Schmidt
;>>        http://www.cliki.net/Jochen%20Schmidt
;>>    Libre Software Meeting 2004
;>>        http://www.cliki.net/Libre%20Software%20Meeting%202004
;>>    Lisp books
;>>        http://www.cliki.net/Lisp%20books
;>>    LMud
;>>        http://www.cliki.net/LMud
;>>    mel-base
;>>        http://www.cliki.net/mel-base
;>>    Naming conventions
;>>        http://www.cliki.net/Naming%20conventions
;>>    psgraph
;>>        http://www.cliki.net/psgraph
;>>    Roland Kaufmann
;>>        http://www.cliki.net/Roland%20Kaufmann
;>>    rt
;>>        http://www.cliki.net/rt
;>>    sb-sprof-ui
;>>        http://www.cliki.net/sb-sprof-ui
;>>    Screenshots
;>>        http://www.cliki.net/Screenshots
;>>    Suggested Programming Projects
;>>        http://www.cliki.net/Suggested%20Programming%20Projects
;>>    SWINE
;>>        http://www.cliki.net/SWINE
;>>    thread
;>>        http://www.cliki.net/thread
;>>    Vladimir Sedach
;>>        http://www.cliki.net/Vladimir%20Sedach
;>>    WeirdIRC
;>>        http://www.cliki.net/WeirdIRC
;>>    YoungLispers
;>>        http://www.cliki.net/YoungLispers
;>>  
;>>   GitHub
;>>   ------
;>>    clim-doc
;>>        https://github.com/mmontone/clim-doc
;>>    clim-chess
;>>        https://github.com/stassats/clim-chess
;>>    McCLIM
;>>        https://github.com/robert-strandh/McCLIM
;>>    clim-class-browser
;>>        https://github.com/pocket7878/clim-class-browser
;>>    clim-cl-gtk2
;>>        https://github.com/MakarovAlexey/clim-cl-gtk2
;>>    mcclim
;>>        https://github.com/slyrus/mcclim
;>>    CLIMatis
;>>        https://github.com/robert-strandh/CLIMatis
;>>    climacs
;>>        https://github.com/mathrick/climacs
;>>    Climacs
;>>        https://github.com/LaPingvino/Climacs
;>>    climacs
;>>        https://github.com/quek/climacs
;>>    climc
;>>        https://github.com/nlamirault/climc
;>>    climon
;>>        https://github.com/nlamirault/climon
;>>    spectacle
;>>        https://github.com/slyrus/spectacle
;>>    Compta
;>>        https://github.com/robert-strandh/Compta
;>>    climp
;>>        https://github.com/sviridov/climp
;>>    clime
;>>        https://github.com/mon-key/clime
;>>    climbe
;>>        https://github.com/fjames86/climbe
;>>    mcclim
;>>        https://github.com/timoore/mcclim
;>>    mcclim-uim
;>>        https://github.com/quek/mcclim-uim
;>>    LisPod
;>>        https://github.com/pocket7878/LisPod
;>>    ernestine
;>>        https://github.com/nlamirault/ernestine
;>>    sudoku-mcclim
;>>        https://github.com/tortkis/sudoku-mcclim
;>>    math-interactor
;>>        https://github.com/OlafMerkert/math-interactor
;>>    Second-Climacs
;>>        https://github.com/robert-strandh/Second-Climacs
;>>    climacs-g000001
;>>        https://github.com/g000001/climacs-g000001
;>>    info.read-eval-print.climacs.ext
;>>        https://github.com/quek/info.read-eval-print.climacs.ext
;>>    info.read-eval-print.climacs.dired
;>>        https://github.com/quek/info.read-eval-print.climacs.dired
;>>  
;>>   BitBucket
;>>   ---------
;>>    climacs-clim-listener-beirc
;>>        https://bitbucket.org/wbooze/climacs-clim-listener-beirc
;>>    com.symsim.oss.collada-gui
;>>        https://bitbucket.org/symbolicsimulation/com.symsim.oss.collada-gui
;>>  
;=>  CL:T

 オプションが色々取れるのですが、シェルのキーワードのように合体して記述できるところが便利です。

(qs:? "clim" :u :g)(qs:? "clim" :ug)

まとめ

 今回は、quicksearchを紹介してみました。
これは結構便利そうなので活用して行きたいところです。
エディタのコマンドから使えると、更に便利そうですね。

modfの紹介

Posted 2014-04-08 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の99日目です。

modfとはなにか

 modfは、Zach Kost-Smith氏作の「非破壊的SETF」のようなものです。

パッケージ情報

パッケージ名modf
Quicklisp
参考サイト
Quickdocshttp://quickdocs.org/modf

インストール方法

(ql:quickload :modf)

試してみる

 どんな関数があるかは、Quickdocsで確認できます。

 上では非破壊的SETFなどという表現をしましたが、どういうものかというと、READMEにも詳しいですが、

(let ((foo (*:iota 15)))
  (list (modf (tenth foo) '--)
        foo))
;=>  ((0 1 2 3 4 5 6 7 8 -- 10 11 12 13 14) (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14))

のように、元のオブジェクトを変更することはなしに、元のオブジェクトの一部を変更したものを返すというものです。

 クラスのオブジェクト等、Common Lisp標準のデータ型にも対応しています。

(defclass foo () 
  ((a :initform 0)))


(let ((o (make-instance 'foo)))
  (list (slot-value (modf (slot-value o 'a) 1) 'a)
        (slot-value o 'a)))
;=>  (1 0)

 コピーしてSETFすれば良いんじゃないのかというところもありますが、その辺りをすっきり纏めてくれるところが便利なのではないでしょうか。
ちなみにリストは、コピーしてSETFではなく、新規にCONSする戦略のようです。

 また、SETFのようにmodfでもユーザーに拡張する手段が提供されています。
主な道具は、

  • define-modf-expander
  • define-modf-method
  • define-modf-rewrite

ですが、-expanderと、-methodの方は対応するSETFのものから使い方も想像が付くかなと思います。
-rewriteは、(caar ...) -> (car (car ...))等、複合したオペレーターを分解するルールを記述するのに使います。

まとめ

 今回は、modfを紹介してみました。
元のオブジェクトには変更を加えないで一部分だけ変えたいということは、それなりにあるかなと思いますが、modというとどうも元のオブジェクトを変更するような動作を想像してしまいます。copyf等でも良かったような、そうでもないような。

pythonic-string-readerの紹介

Posted 2014-04-07 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の98日目です。

pythonic-string-readerとはなにか

 pythonic-string-readerは、Yury Sulsky氏とZach Kost-Smith氏によるPythonの3重クォート的なものををCommon Lispに導入するライブラリです。

パッケージ情報

パッケージ名pythonic-string-reader
Quicklisp
Quickdocshttp://quickdocs.org/pythonic-string-reader

インストール方法

(ql:quickload :pythonic-string-reader)

試してみる

 どんな関数があるかは、Quickdocsで確認できます。

 pythonic-string-readerでは、named-readtablesでリードテーブルが定義されているので、それを使うのが簡単です。

"""foo"""
""" "foo" """
""" hello\ """
""" hello\ """" "
"""hello"""
"hello"
""" \ """
" \\ "
""" " " """
" \" \" "
"""" hello """"
"""" hello """ " """"
"\x86"
"""
foo
"""
"""
"bar"
"""

というような内容のfooというファイルがあった場合、pythonic-string-readerのリードテーブルを使えば、

(let ((*readtable* (*:find-readtable
                    'pythonic-string-reader:pythonic-string-syntax)))
 (with-open-file (in "foo")
   (loop :for xpr := (read in nil in) :until (eq xpr in)
         :do (print xpr))))
;>>  
;>>  "foo" 
;>>  " \"foo\" " 
;>>  " hello\\ " 
;>>  " hello\\ " 
;>>  " " 
;>>  "hello" 
;>>  "hello" 
;>>  " \\ " 
;>>  " \\ " 
;>>  " \" \" " 
;>>  " \" \" " 
;>>  " hello " 
;>>  " hello \"\"\" \" " 
;>>  "x86" 
;>>  "
;>>  foo
;>>  " 
;>>  "
;>>  \"bar\"
;>>  " 
;=>  NIL

のように読まれます。
簡単に言えば、ダブルクォートと、バックスラッシュをエスケープ文字なしに記述できる、というところです。Pythonのように\x22を'"'のように読んだりまではしない模様です。
また、named-readtablesを使いたくない人の為に、ENABLE-PYTHONIC-STRING-SYNTAX、DISABLE-PYTHONIC-STRING-SYNTAX関数も用意されています。

まとめ

 今回は、pythonic-string-readerを紹介してみました。
Common Lispの文字列では\n、\t等、C的な文字列の記法をサポートしていませんが、リーダーマクロでサポートしてしまうというのもアリといえばアリですね。

Older entries (1621 remaining)