Web Images Videos Maps News Shopping Gmail more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Message from discussion Lisp Design Patterns
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Rainer Joswig  
View profile  
 More options Sep 26 2008, 3:19 pm
Newsgroups: comp.lang.lisp
From: Rainer Joswig <jos...@lisp.de>
Date: Fri, 26 Sep 2008 21:19:59 +0200
Local: Fri, Sep 26 2008 3:19 pm
Subject: Re: Lisp Design Patterns
In article
<b4441692-2db8-46b2-893e-10b26d424...@l42g2000hsc.googlegroups.com>,

 vttoonses <vttoon...@gmail.com> wrote:
> On Sep 26, 1:21 pm, Bakul Shah <bakul+use...@bitblocks.com> wrote:
> > Rainer Joswig wrote:
> > > That's not a 'design pattern'. That's architecture.

> > Concise, funny & profound (meaning: exactly my sentiments!).
> > An epigram worthy of fortune(1).

> Actually, I was trying to ask a general question and provide some
> context within which it made sense.

> "This is how I would normally construct my application at a macro
> level (architecture). Before I spend a lot of time spinning my wheels
> attempting to apply concepts at a micro level (design patterns), is
> there something I should know as how developing in Lisp might affect
> these areas?"

I don't really think in those object-oriented design patterns
of the GoF book. I've seen Java developers doing it.
I don't.

See for example this Python code from
http://en.wikipedia.org/wiki/Factory_method_pattern:

class Pizza:
    HAM_MUSHROOM_PIZZA_TYPE = 0
    DELUXE_PIZZA_TYPE = 1
    SEAFOOD_PIZZA_TYPE= 2

    def __init__(self):
        self.__price = None

    def getPrice(self):
        return self.__price

class HamAndMushroomPizza(Pizza):
    def __init__(self):
        self.__price = 8.50

class DeluxePizza(Pizza):
    def __init__(self):
        self.__price = 10.50

class SeafoodPizza(Pizza):
    def __init__(self):
        self.__price = 11.50

class PizzaFactory:
    def createPizza(self, pizzaType):
        if pizzaType == Pizza.HAM_MUSHROOM_PIZZA_TYPE:
            return HamAndMushroomPizza()
        elif pizzaType == Pizza.DELUXE_PIZZA_TYPE:
            return DeluxePizza()
        elif pizzaype == Pizza.SEAFOOD_PIZZA_TYPE:
            return SeafoodPizza()
        else:
            return DeluxePizza()

pizzaPrice = PizzaFactory().createPizza(Pizza.HAM_MUSHROOM_PIZZA_TYPE).getPrice()

That's so ugly. Amazingly ugly. Probably there are
better ways to do it in Python...

Imagine (for a moment) you would write that in Lisp:

(defclass pizza ()
  ((price :type integer :accessor pizza-price)))

(defclass ham-and-mushroom-pizza (pizza)
  ((price :initform 8.50)))

(defclass deluxe-pizza (pizza)
  ((price :initform 10.50)))

(defclass seafood-pizza (pizza)
  ((price :initform 11.50)))

(defmethod make-pizza ((type (eql 'gimme-some-ham-and-mushroom-pizza)))
  (make-instance 'ham-and-mushroom-pizza))

(defmethod make-pizza ((type (eql 'gimme-some-deluxe-pizza)))
  (make-instance 'deluxe-pizza))

(defmethod make-pizza ((type (eql 'gimme-some-seafood-pizza)))
  (make-instance 'seafood-pizza))

(defun give-me-some-pizza (what)
  (make-pizza what))

(pizza-price (give-me-some-pizza 'give-me-some-ham-and-mushroom-pizza))

Arrrrrrrrrrrrrrrrrrrrrrrrggghhh!!!!!

Then you think let's get rid of the methods:

(defclass pizza ()
  ((price :type integer :accessor pizza-price)))

(defclass ham-and-mushroom-pizza (pizza)
  ((price :initform 8.50)))

(defclass deluxe-pizza (pizza)
  ((price :initform 10.50)))

(defclass seafood-pizza (pizza)
  ((price :initform 11.50)))

(defparameter *pizza-assoc-list*
  '((give-me-some-ham-and-mushroom-pizza ham-and-mushroom-pizza)
    (give-me-some-deluxe-pizza deluxe-pizza)
    (give-me-some-seafood-pizza seafood-pizza)))

(defun give-me-some-pizza (what)
  (make-instance (second (assoc what *pizza-assoc-list*))))

But then you think WTF, WTF, WTF:

(defclass pizza ()
  ((price :type integer :accessor pizza-price)))

(defmacro defpizza (name price)
  `(defclass ,name (pizza)
     ((price :initform ,price))))

(defpizza ham-and-mushroom-pizza 8.50)
(defpizza deluxe-pizza 10.50)
(defpizza sea-food-pizza 11.50)

(defun make-pizza (class)
  (make-instance class))

(pizza-price (make-pizza 'ham-mushroom-pizza))

Pass the class name directly. If you want to do something
just program it. Forget the factory pattern. Just write
it like you would do it in Lisp. Why would you number
your classes?

If you would really need numbers for classes, then you would just lookup
the class from a table.

(defclass pizza ()
  ((price :type integer :accessor pizza-price)))

(defparameter *number-to-pizza-table* (make-hash-table))

(defmacro defpizza (name &key price number)
  `(progn
     (defclass ,name (pizza)
       ((price :initform ,price)))
     (setf (gethash ,number *number-to-pizza-table*) ',name)))

(defpizza ham-and-mushroom-pizza :price 8.50  :number 0)
(defpizza deluxe-pizza           :price 10.50 :number 1)
(defpizza sea-food-pizza         :price 11.50 :number 2)

(defun make-pizza (number)
  (make-instance (gethash number *number-to-pizza-table*)))

(pizza-price (make-pizza 2))

Suddenly the code gets a whole lot more descriptive.
That's why people say Lisp code can be extremely readable.
All the special pizza stuff can be changed in one
macro. All the domain definitions then are done
using the macros. These domain definitions then are dense.

How would you name a pattern from where you would derive
such a solution??? The FACTORY-PRIMITIVE-DSL-AND-TABLE-PATTERN?

The important thing is not the technical solution
how to create the the classes and then the objects.
It is much more important to get the linguistic interface
for the programmer right. That's what a good Lisp
programmer looks for: good surface code. The implementation
is secondary - it will be generated anyway. Then you
also can forget about refactoring. Change the code
generators. Done. Lisp is not about dead code that stands
in your way. Lisp is about creating the right surface code.
That's why Lisp books like PAIP are like code poetry.

What you NEED to learn is to live with the flexibility of Lisp
and acquire some taste about what code looks good,
is easy to read, easy to extend, easy to look at in
the debugger and so on...

--
http://lispm.dyndns.org/


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google