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-04-10

CLで学ぶ「プログラミングGauche」 (5.5)

| 09:03 | CLで学ぶ「プログラミングGauche」 (5.5) - わだばLisperになる を含むブックマーク はてなブックマーク - CLで学ぶ「プログラミングGauche」 (5.5) - わだばLisperになる

今回は5.5章から再開です。

一連のエントリを読み返してみると、あたかもCLについて詳しく知っているように書いてしまっている気がしますが、実際のところ全然詳しくないので、間違いがあったら是非ツッコんで頂けると嬉しいです。

5.5 名前と予約語

Schemeには予約語がないそうですが、CLはどうなんでしょう。調べても良く分かりませんでした。

特に予約語という記述もないので、似たような状況だとは思うのですが…。

システムの根幹に関わるものの名前を再定義することは可能だったりはしますが、警告やエラーになったりもします。

また、メジャーな処理系では拡張でパッケージをロックする仕組みもあり、根幹のCOMMON-LISPパッケージ等の内容を上書きで再定義しようとすると、パッケージロックのエラーになります。

5.6 モジュールを使う

GaucheではSchemeの拡張としてモジュールの仕組みがありますが、CLでは標準のパッケージの仕組みが相当するかと思います。

ただ、CLのパッケージは、名前空間を分けるということが主で、モジュールのロードの仕組み等まで規定するものではありません。

Emacsのように、PROVIDEや、REQUIREというものもありますが、Emacsのようにロードする仕組みがきっちりと決まっている訳ではなくて具体的にファイルをロードする仕組みは処理系依存になります。中途半端に悩ましいことも多い気もしますが、最近では、ASDFというモジュールをロードする仕組みがメジャーになりつつあるようで処理系によっては、標準でREQUIREがASDFを呼び出すようになっているものもあります(SBCL等)。

PROVIDEは*modules*にパッケージ名を追加登録するだけのものです。割と、provideでなく(pushnew :foo *modules*)などと書かれていることも多く、また、ASDFでロードされたパッケージも*modules*に追加する人もいれば、いない人もいるという感じでなんだか適当な現状です。

また、CLは#+、#-等で処理系の違いを吸収する記述が可能で、依存個所を分けて記述し、一つのソースを色々な処理系で読み込ませることが普通に行われています。

これは、MacLISPから続く伝統であり、CL、MacLISP、Zetalisp、Franz Lisp等、MacLISP系のLISPであれば、共通のソースファイルを使用することも可能です。(それなりに面倒なこともありますが…。)

5.7〜5.8 SRFI

SRFIはSchemeの共通のライブラリとして非常に有効に機能していますが、CLの人々にはそのような共通のライブラリを持つという考えは薄いのか、割とばらばらな様子です。元から抱えてるものが多いというのもあるでしょう。CLRFIというSRFIを手本にした動きもありますが、活溌ではないようです。

とはいえ、最近では、ASDFが共通の基盤になりつつあるので、定番なものは、ASDFで簡単に導入できるようになっていることが殆どです。

また、ネットワークインストール等に対応したASDF-INSTALLもあり、Debianのapt-getのように、(asdf-install:install :foo)でインストール可能で非常に便利ではあります。

CLのANSI標準が決まってから月日も流れ、今日必要とされている機能が規定されていないことなどが色々と議論されることも多くなってきているようです。

現状CLに足りていないものについては、CL界の大御所であるDaniel Weireb氏が纏めている下記のエントリの後半が非常に参考になります。

ということで、次回は、6章から再開したいと思います。

GOOでL-99 (P09 連続して現われる要素を纏める)

| 04:23 | GOOでL-99 (P09 連続して現われる要素を纏める) - わだばLisperになる を含むブックマーク はてなブックマーク - GOOでL-99 (P09 連続して現われる要素を纏める) - わだばLisperになる

今回も無駄にリストだけでなくコレクションクラスに対応してみました。

また、GOOでは、繰り返しの為の値の蓄積にpackerというものが使えるようなので使ってみました。

packer-fabでpakerのインスタンスを作成し、pack-inで蓄積、packedで蓄積結果を任意のクラスで返します。割とややこしい使い勝手。


(my-pack '(a a a a b c c a a d e e e e))
;=> ((a a a a) (b) (c c) (a a) (d) (e e e e))
(my-pack #(a a a a b c c a a d e e e e))
;=> #((a a a a) (b) (c c) (a a) (d) (e e e e))
(my-pack #[a a a a b c c a a d e e e e])
;=> #[(a a a a) (b) (c c) (a a) (d) (e e e e)]
(my-pack "aaaabccaadeeee")
;=> "aaaa,b,cc,aa,d,eeee"

(dm my-pack (u|<col> => <col>)
  (if (empty? u)
      u
      (as (class-of u) (my-pack1 u))))

(dm my-pack (u|<str> => <str>)
  (if (empty? u)
      u
      (join (map (op as <str> _) 
                 (my-pack1 u))
            ",")))

(df my-pack1 (u|<col> => <lst>)
  (let ((prev (1st u))
        (res (packer-fab <lst>))
        (tem (packer-fab <lst>)))
    (for ((x u))
      (unless (= x prev)
        (pack-in res (packed tem))
        (set tem (packer-fab <lst>)))
      (pack-in tem x)
      (set prev x))
    (pack-in res (packed tem))
    (packed res)))

;))))))))))

QiでL-99 (P25 ランダムに並び換え)

| 02:36 | QiでL-99 (P25 ランダムに並び換え) - わだばLisperになる を含むブックマーク はてなブックマーク - QiでL-99 (P25 ランダムに並び換え) - わだばLisperになる

(rnd-permu [a b c d e f])
\=> [e a d f c b]
\

(define rnd-permu
  U -> (rnd-select U (length U)))