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-07-01

サンプルコードによるLOOPマクロ入門 (4)

| 23:11 | サンプルコードによるLOOPマクロ入門 (4) - わだばLisperになる を含むブックマーク はてなブックマーク - サンプルコードによるLOOPマクロ入門 (4) - わだばLisperになる

フィルター

:collectを使って値を集めてリストにする方法を取り上げてきましたが、ただ集めるだけでなくて、対象を選別しつつ集めたいこともあります。

そのような場合には、:if、:when、:unless等の述語と:collectとを組み合わせます。

(loop :for i :in '(1 2 3 4 5 6 7) 
      :do (when (oddp i) :collect i))

のように書けば良さそうなものですが、飽くまで:collectは、LOOPのキーワードであり、LOOPの中でしか機能しないので、通常の式の中に組み込んで使うことができません。

ということで、

(loop :for i :in '(1 2 3 4 5 6 7) 
      :when (oddp i) :collect i)
;=> (1 3 5 7)

となります。

また、これらの述語と組み合わせると、:collectでは、:itで述語の結果を参照できるので

(loop :for i :in '(1 2 3 4 5 6 7) :when (and (oddp i) i) :collect :it)
;=> (1 3 5 7)

とも書けます。ちなみに、ここでは、わざわざ:itを使うために述語の部分が冗長になっていますが、

(loop :for i :in '(1 () 2 () 3 () 4) :when i :collect :it)
;=> (1 2 3 4)

という風に、nilか真値を返すような述語を使う場合に便利かもしれません。

また、:if、:when、:unlessは、2系統に分岐することができます。

(loop :for i :in '(1 2 3 4 5 6 7) 
      :when (oddp i)
        :collect i
      :else
        :collect '?
      :end)
;=> (1 ? 3 ? 5 ? 7)

若干ややこしいのですが、LOOPの:whenは、通常のLISPのwhenと違い、:ifとまったく同じなもので単なる別名です。

また、:endというキーワードが使えて区切りをハッキリさせる目的で使えます。