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 |

2009-02-04

CLでぱっとしない関数

| 00:07 | CLでぱっとしない関数 - わだばLisperになる を含むブックマーク はてなブックマーク - CLでぱっとしない関数 - わだばLisperになる

CLでは、別に不便というわけでもないのに、あまりぱっとしない関数があるように思えます。

例えば、write

(let ((*print-base* 16))
  (prin1 22))

とか書くなら

(write 22 :base 16)

と書けますし、write単体でも、prin1とかいう名前より馴染み深いと思うのですが、あまりぱっとしません。

自分のなかでは、writeは何故かプリミティブなものという印象があります。

その他だと、map。

mapは、リストだけでなくシーケンス全般に使えて、結果の型も指定できるので割と万能なやつなのですが、リストなら、mapcarですし、アレイなら、loopというところで、これもぱっとしません。

(map nil (lambda ...)
  ...)
;=> nil

とかにすると、最後にnilを返すことで副作用目的ですよ、ということを主張できる気がして好きなんですが、汎用だけに遅かったりするのかしらとか思うと、

(progn
  (mapc (lambda ...)
    ...)
 nil)
;=> nil

なんて書いてしまうわけですね。実際、こういうコードの方が多いですし。

というかこの場合はmapcの返り値にも問題があるわけですが。

あとは強いて挙げるなら、elt。

elementの略だというのがわかりづらい名称でシーケンス全般から要素を取り出す汎用的なものですが、遅いというイメージを持たれているのか、専用関数に置き換えられることが多いようです。

しかし、Lispマシンのマニュアルによると、タグマシンだと型はハードウェアで区別できるので、eltも専用関数も効率は変わらないという説明があったりします。ビバLispマシン。

そういうことを聞くとできるだけ汎用的な関数を使いたくなってしまいます。

ということで、elt vs aref、elt vs nthを比較してみましたが、SBCLやSCLだと殆ど差はないようです。

しかし、Clozure CLだと実に20倍の速度差。

こういう例があるとやっぱり使い分けとか言われちゃいますよね。

でも、Clozure CL以外は、殆ど速度に変化なしみたいですし、個人的にはeltとかmapとか多用して行きたいかなと思います。

ぱっとしない関数全般に言えるのは、MacLISPに存在せず、Zetalisp後期か、Common Lispになってから導入されたものが多いんじゃないかというところです。逆に置き換えに成功した事例としては、block+tagbody vs progがあるように思えます。ちなみに、そのprogもなくなったわけではありません。

伝統を継承しつつ新しくするというのは、色々大変なのかもしれません。

ゲスト



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