ccc31807 <
cart...@gmail.com> writes:
> On May 22, 2:13 am, "Pascal J. Bourguignon" <
p...@informatimago.com>
> wrote:
>> The thing with "runnable pseudo code" (see url above), is that if you
>> just write your specification or your design in sexp form, then you can
>> write in lisp the program that transforms in into the next form.
>> Then your "source code" will be your specification or your design, and
>> it will explain by itself the application because it will BE itself the
>> application!
>
> This begs the question. OO design has been heavily formalized, books
> have been written about OO design and courses taught, and I've taken
> two of them so far. We can do class diagrams, state diagrams, sequence
> diagrams, and the like. These diagrams can be directly translated into
> OO templates, and the diagrams can be generated from OO code. However,
> this doesn't seem to be true for FP code. Yes, if I wanted to write OO
> Common Lisp, then UML and the OO design techniques would be valuable
> if not mandatory. My question was directed toward writing FP code.
Remember the equivalence between objects and closures.
(let ((x 0)
(y 0))
(defun f (m &optional a)
(ecase m
(:set (check-type a integer) (setf y a))
(:inc (incf x) (decf y) (when (zerop y) 'bing))
(:get x))))
is the same as:
(defclass f ()
((x :initform 0 :accessor f-x)
(y :initform 0 :accessor f-y)))
(defmethod f-set ((f f) a)
(with-slots (x y) f
(check-type a integer)
(setf y a)))
(defmethod f-get ((f f))
(with-slots (x y) f
x))
(defmethod f-inc ((f f))
(with-slots (x y) f
(incf x) (decf y) (when (zerop y) 'bing)))
(progn
(f :set 3)
(list (f :inc) (f :inc) (f :inc) (f :inc) (f :get)))
--> (nil nil bing nil 4)
(let ((f (make-instance 'f)))
(f-set f 3)
(list (f-inc f) (f-inc f) (f-inc f) (f-inc f) (f-get f)))
--> (nil nil bing nil 4)
Of course, CLOS gives you some syntactic sugar and niceties, but nothing
you couldn't implement easily enough just with closures.
So, like a mathematician, you can answer all your questions about FP by
converting closures to objects, answering the question in OO, and
converting back the answer to closures.
>> > Here's the question: Are there design best practices for Common Lisp
>> > in particular, and functional languages in general, similar to the top-
>> > down, step-wise refinement development methodology taught in software
>> > engineering courses?
>>
>> If they're best practice in software engineering, what makes you think
>> they're not best practice writing Common Lisp programs? Is writing Lisp
>> programs not software engineering?
>
> How would you go about generating design documents in CL? If I were
> writing OO code, I would use UML, patterns, and all the other tricks.
Just the same.
UML is not about Object Oriented Programming. It is about a Unified
MODELING Language. You can model anything with it. For example, the
metabolism of cells.
http://www.ncbi.nlm.nih.gov/pubmed/15888343
So if you know some UML, you can describe a lisp program with it. Or a
specification. Or a design.
> If I were writing procedural code (which I do -- a lot), then I would
> use flow charts and pseudocode. Both these activities are largely top
> down. How do you create design documents bottom up? The best answer I
> can come up with is that you design DSLs to solve basic problems, and
> then use those to build your higher level code. However, this approach
> seems to be entirely different that doing design work as we
> customarily understand it.
Nobody forces you to write the design document before the
implementation, or to write the high level description before the low
level details. You can develop and write them in the order you want.
Just use small cycles to refine them a lot.
It's to be able to read them and understand a complex system more easily
that we start reading the specifications, then the design, then the
sources, and that we start by reading high level descriptions or parts
before reading the low level details. But this sorting is done only as
a last editing step, it's not a development process.
>> Right there under your nose! Just apply what you learned in your
>> software engineering classes!!!
>
> If I could do that, I wouldn't have asked the question.
>
>> So you have net objects with a bias attribute.
>> Net objects are in relationship with an indexed set of layer objects.
>> Layer objects are in relationship with an indexed set of node objects.
>> A node seems to have children and parents, and those relationships have
>> a weight attribute.
>
> You are either suggesting to draw a control flow graphs, which
> essentially amounts to a flow chart, or else to generate some kind of
> network graph or tree. I do not know how to do this in the context of
> program design.
No, I'm suggesting that a set of function signatures define one or more
abstract data types, and that an ADT is just an OO class.
What I'm saying is that I see no difference between:
> (defun layer-count (net)
> (defun get-bias (net)
> (defun node-count (net layernum)
> (defun get-layer (net layernum)
> (defun get-node (net layernum nodenum)
> (defun get-child-weights (net layernum nodenum)
> (defun get-parent-weights (net layernum nodenum)
> (defun get-weight-list (node)
> (defun get-nth-weights (layer n)
(defclass net (…) (…))
(defclass layer (…) (…))
(defclass node (…) (…))
(defmethod get-bias ((self net)) …)
(defmethod get-layer ((self net) layernum) …)
(defmethod node-count ((self layer)) …)
(defmethod get-node ((self layer) nodenum) …)
(defmethod get-child-weights ((self node)) …)
(defmethod get-parent-weights ((self node)) …)
(defmethod get-weight-list ((self node)) …)
(defmethod get-nth-weights ((self layer) n) …)
>> You don't need to read the body, just the signatures, to understand it.
>
> So how do I understand this function signature?
> (add-results-to-table (t r a n) [don't need to read the body to
> understand the function] )
It is bad code, since the parameter names are not explicit. It should be
rejected from the code review.
> I said that this was not a hypothetical question. If I wanted to
> design an artificial neural network in the functional style, how would
> I go about doing it?
Natural neural network use the physical world which is full of state and
mutation. It is silly to try to implement them in the functional
(mutation-free) style. You can still do it, considering that each
change of state in the neural network actually forks a new copy of the
neural network with a few differences. Once you do that, there's no
difference between functional programming and the other mutation-full
programming styles.
In any case, see above. You have a set of function signatures that
works perfectly well in the functional style, and they're equivalent to
the classes and methods I described.