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

CLとデザインパターン - Template Method

| 23:09 | CLとデザインパターン - Template Method - わだばLisperになる を含むブックマーク はてなブックマーク - CLとデザインパターン - Template Method - わだばLisperになる

どういう訳かLISP系言語とデザインパターンについて以前から興味があります。

しかし、どうもデザインパターンの解説が馴れないと難解というか、コードの例もUML図もさっぱり分からないことが多いので、さっぱり理解できません。

といっても、このままでは、何も分からないままなので、とりあえず理解できそうなところから手を付けて行くことにしました。

基本的に手引とするのは、Norvig氏のDesign Patterns in Dynamic LanguagesとGreg Sullivan氏のGOF Design Patterns in a Dynamic OO Languageの文献と、矢沢久雄氏のITproでの連載-no titleです。

今回は、一番簡単っぽい、Template Methodを考えてみることにしました。

Template Method

Template Methodとは、具体的な処理をサブクラスにまかせるパターンとのこと。雛型のクラスを作成し、そこで抽象的な処理の流れを記述して、具体的な処理の記述は、サブクラスで行なうというパターンのようです。

それで、上述のNorvig氏の資料によれば、LISPの場合、関数がファースト・クラスなので取り立ててパターンとして意識されることもない、というような説明があります。

とりあえず、どういうことなのか良く分からないので

の内容を参考に適当にコードを書いてみました。

高階関数版
(defun template-function (&optional (op1 #'values) (op2 #'print))
  (lambda (string)
    (funcall op2 (funcall op1 string))))

(defun op1 (string)
  (string-upcase string))

(defun op1-1 (string)
  (string-capitalize string))

(defun op2 (string)
  (print string))

(let ((abstract (template-function))
      (concrete (template-function #'op1 #'op2))
      (concrete1 (template-function #'op1-1 #'op2)))
  (funcall abstract "foo bar baz")
  (funcall concrete "foo bar baz")
  (funcall concrete1 "foo bar baz"))

;>>> "foo bar baz" 
;>>> "FOO BAR BAZ" 
;>>> "Foo Bar Baz" 

関数をとって、手順を合成した関数を返すというtemplate-functionを作成してみています。

この場合、template-functionは全体の流れだけを保持しているような感じです。

次にクラスを使って書いてみました。

クラス版
(progn
  (defclass abstract () () )
  
  (defmethod op1 ((class abstract) (string string))
    string)
  (defmethod op2 ((class abstract) (string string))
    string)
  (defmethod template-method ((class abstract) (string string))
    (op2 class (op1 class string))))
  
(progn
  (defclass concrete (abstract) () )

  (defmethod op1 ((class concrete) (string string))
    (string-upcase string))
  (defmethod op2 ((class concrete) (string string))
    (format t "~A~%" string)))

(progn
  (defclass concrete2 (abstract) () )

  (defmethod op1 ((class concrete2) (string string))
    (string-capitalize string))
  (defmethod op2 ((class concrete2) (string string))
    (princ string)
    (terpri)))

(template-method (make-instance 'concrete) "foo bar baz")
;>>> FOO BAR BAZ

(template-method (make-instance 'concrete2) "foo bar baz")
;>>> Foo Bar Baz

(template-method (make-instance 'abstract) "foo bar baz")
;=> "foo bar baz"

何となく抽象的な雛型を作成しておいて、その穴を埋めるという感じは理解できました。

Template-Methodの場合、情報の隠蔽性も重要なところみたいなのですが、CLOSの場合、隠蔽することに力点を置いてないのと、総称関数なので隠すのはちょっと難しいですね(;´Д`)

隠すとしたら、パッケージの機能でメインの関数だけをexportする等の方法になるんでしょうか。

ClojureでL-99 (P15 要素を任意回数複製する)

| 18:37 | ClojureでL-99 (P15 要素を任意回数複製する) - わだばLisperになる を含むブックマーク はてなブックマーク - ClojureでL-99 (P15 要素を任意回数複製する) - わだばLisperになる

この問題は、2つ星で難しめということになっているのですが、Prologだとこういうのは難しかったりするんでしょうか。

(defn 
  #^{:doc "P15 (**) Replicate the elements of a list a given number of times."
     :test (do (test= (repli [] -1) [])
               (test= (repli [1 2] 0) nil)
               (test= (repli [1 2] -1) nil)
               (test= (repli '(a b c) 3)
                      '(a a a b b b c c c))) }
; -----
  repli
; -----
  ([coll n]
     (reduce #(concat %1 (take n (repeat %2)))
             []
             coll)))

10/4 第19回 慢性的CL勉強会@Lingr 8時だョ!全員集合 告知

| 01:49 | 10/4 第19回 慢性的CL勉強会@Lingr 8時だョ!全員集合 告知 - わだばLisperになる を含むブックマーク はてなブックマーク - 10/4 第19回 慢性的CL勉強会@Lingr 8時だョ!全員集合 告知 - わだばLisperになる

今回も告知が遅くなってしまいました。今週もCL勉強会は開催させて頂きます!

今回のお題はいきなりですが、Let Over Lambdaの1〜4章の概要をさらってみることにしてみました。

Let Over LambdaはOn Lispの流れを推し進めたような本で、主にマクロの本なのですが、4章までは割と基礎的なところも多く、その割に妙なところもあるので面白いかと思います。

こちらから4章までは、無料でウェブ上で読めます。

また、今回から、時間を大幅に短縮して、20:00〜20:30の30分間でできる範囲にしたいと思います。

その後ですが、主に雑談タイムとすることを考えています。

場所:Lingr: Common Lisp部屋
日時10/4 (土) 20:00から適当(途中参加/離脱/ROM歓迎)
勉強会の進行Let Over Lambda 1〜4
勉強会の目標CLに関して一つ位賢くなった気になること
時刻お題対象者参考リンク
20:00-20:30位までLet Over Lambda 1〜4CLのマクロが好きな方Let Over Lambda

勉強会のネタがあれば、このブログにコメント頂くか、Lingr等に書き置きしてみて下さい。好きなテーマを持ち込んでみて頂くというのも大歓迎です!