From: J Kenneth King
Subject: proper factory method form
Date: 
Message-ID: <878wnsubbp.fsf@agentultra.com>
I've a growing collection of sub-classes which I hide behind a factory
method. Nothing too out-of-the-ordinary. I'm just looking for the
idiomatic approach and haven't found anything by digging through google,
group archives, et al.

I have something akin to the following:

(defclass ship ()
  ((size :initarg :size
         :initform 0)
   (heading :accessor heading
            :initarg :heading
            :initform 0.0)))

(defclass carrier (ship)
  ((size :initform 5)))

(defclass cruiser (ship)
  ((size :initform 3)))

(defclass tug-boat (ship)
  ((size :initform 1)))

(defun make-boat (type heading)
  (if (find-class type)
      (make-instance type :heading heading)))

Thanks for giving this a once over and a bit of sanity check for me. ;)

Cheers

From: Jeff M.
Subject: Re: proper factory method form
Date: 
Message-ID: <52bce804-677f-46bf-b32f-f94660e99efe@p6g2000pre.googlegroups.com>
On Feb 26, 3:39 pm, J Kenneth King <·····@agentultra.com> wrote:
> I've a growing collection of sub-classes which I hide behind a factory
> method. Nothing too out-of-the-ordinary. I'm just looking for the
> idiomatic approach and haven't found anything by digging through google,
> group archives, et al.
>
> I have something akin to the following:
>

[.. snipped ship example ..]

>
> Thanks for giving this a once over and a bit of sanity check for me. ;)

Sorry, but I'm going to ask something that I can't stand when people
ask it of me...

- Why do you want do that?

It's simple enough, sure, and I understand why people use class
factories in Java, C++, etc (although I think they are horrible, see
http://discuss.joelonsoftware.com/default.asp?joel.3.219431.12).

But, in Lisp, there should be no need for it. Why do:

 (make-boat 'cruiser 30)

As opposed to:

 (make-instance 'cruiser :heading 30)

You only get rid of the keywords. And, presumably, over time the class
hierarchy will change enough that make-boat will start needing &whole
and pass everything along to make-instance, essentially nullifying any
advantage it originally had.

That would be my predictive guess anyway. But, perhaps your example
was just a super-scaled down version of something much bigger for
which your factory makes more sense. In which case, my apologies. ;)

Now, if there was only 1 ship class or struct:

 (defstruct ship (heading 0)
                 (hull-capacity 0)
                 (armaments '()))

And you wanted a factory that handled setting all the different
attributes based on the type (assuming data was the only difference
between all the types of ships and methods acted on them all the
same)...

Anyway, if you disagree, I'd love to know more about what you are
really doing and how the class factory helps. Perhaps I'll learn a
practical use for them in Lisp. :)

Jeff M.
From: J Kenneth King
Subject: Re: proper factory method form
Date: 
Message-ID: <874oyfu8gb.fsf@agentultra.com>
"Jeff M." <·······@gmail.com> writes:

> On Feb 26, 3:39 pm, J Kenneth King <·····@agentultra.com> wrote:
>> I've a growing collection of sub-classes which I hide behind a factory
>> method. Nothing too out-of-the-ordinary. I'm just looking for the
>> idiomatic approach and haven't found anything by digging through google,
>> group archives, et al.
>>
>> I have something akin to the following:
>>
>
> [.. snipped ship example ..]
>
>>
>> Thanks for giving this a once over and a bit of sanity check for me. ;)
>
> Sorry, but I'm going to ask something that I can't stand when people
> ask it of me...
>
> - Why do you want do that?
>
> It's simple enough, sure, and I understand why people use class
> factories in Java, C++, etc (although I think they are horrible, see
> http://discuss.joelonsoftware.com/default.asp?joel.3.219431.12).
>
> But, in Lisp, there should be no need for it. Why do:
>
>  (make-boat 'cruiser 30)
>
> As opposed to:
>
>  (make-instance 'cruiser :heading 30)
>
> You only get rid of the keywords. And, presumably, over time the class
> hierarchy will change enough that make-boat will start needing &whole
> and pass everything along to make-instance, essentially nullifying any
> advantage it originally had.
>
> That would be my predictive guess anyway. But, perhaps your example
> was just a super-scaled down version of something much bigger for
> which your factory makes more sense. In which case, my apologies. ;)
>
> Now, if there was only 1 ship class or struct:
>
>  (defstruct ship (heading 0)
>                  (hull-capacity 0)
>                  (armaments '()))
>
> And you wanted a factory that handled setting all the different
> attributes based on the type (assuming data was the only difference
> between all the types of ships and methods acted on them all the
> same)...
>
> Anyway, if you disagree, I'd love to know more about what you are
> really doing and how the class factory helps. Perhaps I'll learn a
> practical use for them in Lisp. :)
>
> Jeff M.

Well, it is a simplification for the benefit of potential readers. ;)

The main rationale for me was to hide the implementation of boats from
callers. If later I want my boats to be implemented as structs, I don't
want to have to wade through calling code and replacing (make-instance)
calls.

Unfortunately I'm still pretty new to Lisp and not familiar with its
unique vernacular. This makes it hard to find the right documentation
I'm looking for as I have to rely on what I already know. Hence the
post.

I'm just looking for the right abstraction to use in this case.
From: Jeff M.
Subject: Re: proper factory method form
Date: 
Message-ID: <d6495979-da60-48b5-bd23-9374232fecb3@v35g2000pro.googlegroups.com>
On Feb 27, 10:54 am, J Kenneth King <·····@agentultra.com> wrote:
> "Jeff M." <·······@gmail.com> writes:
> >
> > Anyway, if you disagree, I'd love to know more about what you are
> > really doing and how the class factory helps. Perhaps I'll learn a
> > practical use for them in Lisp. :)
>
>
> Well, it is a simplification for the benefit of potential readers. ;)
>
> The main rationale for me was to hide the implementation of boats from
> callers. If later I want my boats to be implemented as structs, I don't
> want to have to wade through calling code and replacing (make-instance)
> calls.

Hmm, if that's your primary goal, what might likely be better would be
to just use a macro to generate the class definition for you, and then
simulate what defstruct would do.

I'm not at a machine with Lisp on it right now, and I don't want to
post some seriously wrong code, so someone else could help you with
the macro, but you could do something like this (bad pseudo-code):

MACRO:

define-ship-type (name &rest members)

RESULT (if using classes):

(progn
  (defclass ,name (ship)
    ((member-0 :initarg :member-0 :accessor ,name-member-0)
     (member-1 :initarg :member-1 :accessor ,name-member-0)
     ...))
  (defmacro make-,name (&rest options)
    `(make-instance ',name ,@options)))

RESULT (if using structs):

(defstruct (,name :include ship) ,@members)


I'd actually bet something like this already exists and is out there
somewhere. Also, just as a mental note from someone who's gone through
it the hard way multiple times already: I've found that in Common
Lisp, unless I *know* up front that I need some of the [very powerful]
features of CLOS, 95% of the time defstruct does absolutely everything
that I need and more. So I start with that and then later switch to a
class if it turns out I need it (and that switch is much easier - to
me - than the other way around).

Jeff M.
From: Pascal J. Bourguignon
Subject: Re: proper factory method form
Date: 
Message-ID: <87k57b7okf.fsf@galatea.local>
"Jeff M." <·······@gmail.com> writes:
>> The main rationale for me was to hide the implementation of boats from
>> callers. If later I want my boats to be implemented as structs, I don't
>> want to have to wade through calling code and replacing (make-instance)
>> calls.
>
> Hmm, if that's your primary goal, what might likely be better would be
> to just use a macro to generate the class definition for you, and then
> simulate what defstruct would do.
>
> I'm not at a machine with Lisp on it right now, and I don't want to
> post some seriously wrong code, so someone else could help you with
> the macro, but you could do something like this (bad pseudo-code):
>
> MACRO:
>
> define-ship-type (name &rest members)
>
> RESULT (if using classes):
>
> (progn
>   (defclass ,name (ship)
>     ((member-0 :initarg :member-0 :accessor ,name-member-0)
>      (member-1 :initarg :member-1 :accessor ,name-member-0)
>      ...))
>   (defmacro make-,name (&rest options)

There's no reason for it to be a macro. Make it a function
Use  ,(intern (format nil "MAKE-~A" name)
to insert the function name.

> I'd actually bet something like this already exists and is out there
> somewhere. 

Yes, there are several examples in cll.

-- 
__Pascal Bourguignon__
From: John Thingstad
Subject: Re: proper factory method form
Date: 
Message-ID: <op.upzi4wxuut4oq5@pandora.alfanett.no>
P� Thu, 26 Feb 2009 22:39:54 +0100, skrev J Kenneth King  
<·····@agentultra.com>:

>
> I've a growing collection of sub-classes which I hide behind a factory
> method. Nothing too out-of-the-ordinary. I'm just looking for the
> idiomatic approach and haven't found anything by digging through google,
> group archives, et al.
>
> I have something akin to the following:
>
> (defclass ship ()
>   ((size :initarg :size
>          :initform 0)
>    (heading :accessor heading
>             :initarg :heading
>             :initform 0.0)))
>
> (defclass carrier (ship)
>   ((size :initform 5)))
>
> (defclass cruiser (ship)
>   ((size :initform 3)))
>
> (defclass tug-boat (ship)
>   ((size :initform 1)))
>
> (defun make-boat (type heading)
>   (if (find-class type)
>       (make-instance type :heading heading)))
>
> Thanks for giving this a once over and a bit of sanity check for me. ;)
>
> Cheers

Norvig has a discussion of design patterns in dynamic languages..
He concludes "16 out of 24 patterns are simpler or invisible..."
Look at Abstract Factory Pattern

http://norvig.com/design-patterns/ppframe.htm

-- 
--------------
John Thingstad
From: J Kenneth King
Subject: Re: proper factory method form
Date: 
Message-ID: <87zlg7stj2.fsf@agentultra.com>
"John Thingstad" <·······@online.no> writes:

> På Thu, 26 Feb 2009 22:39:54 +0100, skrev J Kenneth King
> <·····@agentultra.com>:
>
>>
>> I've a growing collection of sub-classes which I hide behind a factory
>> method. Nothing too out-of-the-ordinary. I'm just looking for the
>> idiomatic approach and haven't found anything by digging through google,
>> group archives, et al.
>>
>> I have something akin to the following:
>>
>> (defclass ship ()
>>   ((size :initarg :size
>>          :initform 0)
>>    (heading :accessor heading
>>             :initarg :heading
>>             :initform 0.0)))
>>
>> (defclass carrier (ship)
>>   ((size :initform 5)))
>>
>> (defclass cruiser (ship)
>>   ((size :initform 3)))
>>
>> (defclass tug-boat (ship)
>>   ((size :initform 1)))
>>
>> (defun make-boat (type heading)
>>   (if (find-class type)
>>       (make-instance type :heading heading)))
>>
>> Thanks for giving this a once over and a bit of sanity check for me. ;)
>>
>> Cheers
>
> Norvig has a discussion of design patterns in dynamic languages..
> He concludes "16 out of 24 patterns are simpler or invisible..."
> Look at Abstract Factory Pattern
>
> http://norvig.com/design-patterns/ppframe.htm

Thanks for the link, I'll have to dig around his site to figure out what
he means. Unfortunately, slides without the presentation don't say much.
From: Thomas A. Russ
Subject: Re: proper factory method form
Date: 
Message-ID: <ymi3adztz2v.fsf@blackcat.isi.edu>
J Kenneth King <·····@agentultra.com> writes:

> I've a growing collection of sub-classes which I hide behind a factory
> method. Nothing too out-of-the-ordinary. I'm just looking for the
> idiomatic approach and haven't found anything by digging through google,
> group archives, et al.
...

> (defun make-boat (type heading)
>   (if (find-class type)
>       (make-instance type :heading heading)))
> 
> Thanks for giving this a once over and a bit of sanity check for me. ;)

I'm not sure exactly why you want to have a factory method like this.
Is it just to save on typing a couple keyword arguments?
Or to have a fall-back position in case there is no such class?

Perhaps this is a bit of a hold-over from other programming languages
where you want to have some sort of easy way to dynamically choose the
type?  But MAKE-INSTANCE is already a generalized factory method like
that.

I guess the other reason for a factory method might be to allow for
implementation-specific choices of class to handle a particular
functionality.  But in that case, you normally don't specify the type as
an argument.

So:  What is your goal for having a MAKE-BOAT function?

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: J Kenneth King
Subject: Re: proper factory method form
Date: 
Message-ID: <87sklwrnp3.fsf@agentultra.com>
···@sevak.isi.edu (Thomas A. Russ) writes:

> J Kenneth King <·····@agentultra.com> writes:
>
>> I've a growing collection of sub-classes which I hide behind a factory
>> method. Nothing too out-of-the-ordinary. I'm just looking for the
>> idiomatic approach and haven't found anything by digging through google,
>> group archives, et al.
> ...
>
>> (defun make-boat (type heading)
>>   (if (find-class type)
>>       (make-instance type :heading heading)))
>> 
>> Thanks for giving this a once over and a bit of sanity check for me. ;)
>
> I'm not sure exactly why you want to have a factory method like this.
> Is it just to save on typing a couple keyword arguments?
> Or to have a fall-back position in case there is no such class?

Fallback in case there is no object to create and to hide the
implementation of objects from the outside world.

> Perhaps this is a bit of a hold-over from other programming languages
> where you want to have some sort of easy way to dynamically choose the
> type?  But MAKE-INSTANCE is already a generalized factory method like
> that.

It is a hold-over; I'm learning Lisp as I go and haven't been able to
find a conclusive source of Lisp vernacular. It tends to be spread out
and require much research before much progress is made in programming
anything. I'm willing to research, I just found it difficult to find a
clear answer this time.

> I guess the other reason for a factory method might be to allow for
> implementation-specific choices of class to handle a particular
> functionality.  But in that case, you normally don't specify the type as
> an argument.
>
> So:  What is your goal for having a MAKE-BOAT function?

To abstract the construction of an indefinite set of objects and hide
their implementation from the outside world.

Perhaps it doesn't matter much -- that choosing an implementation is
fine and callers should know the types of objects they are
receiving. Like I mentioned above, I'm just learning as I go and haven't
found a definitive source of design philosophy for Lisp yet. I've built
some not-so-trivial tools and entertaining programs now and have been
getting the feeling that I'm still hanging on to design conventions from
other languages that I have been trained in.

I'm really enjoying my experiences with the language so far, so I'm just
looking to learn more.
From: ··················@gmail.com
Subject: Re: proper factory method form
Date: 
Message-ID: <4528792f-2d4f-4988-ba5a-0e03d8073daf@l39g2000yqn.googlegroups.com>
> Like I mentioned above, I'm just learning as I go and haven't
> found a definitive source of design philosophy for Lisp yet.

In my rather short experience with Lisp I've found this to be true as
well.

I think part of this is because programming lisp involves deciding
what /the best way/ to solve a certain problem would is, and then
extending the language until it is easy to solve your problem
(sometimes these extensions have already been written ex. being Cells
or Fset, or CLOS or the loop macro).

It is a meta-programming paradigm rather than a strict set of rules
(This is blub language style and you /will/ program in it).

At some point the best way to learn Lisp is to learn other non-lisp
languages and beg/borrow/steal the good stuff out of them.