[plt-scheme] Was HTDP 21.1.2 - Why I "don't" use the design recipe

From: wooks . (wookiz at hotmail.com)
Date: Thu Jul 13 05:31:41 EDT 2006

>From: Felix Klock's PLT scheme proxy <pltscheme at pnkfx.org>
>To: "wooks ." <wookiz at hotmail.com>
>CC: plt-scheme at list.cs.brown.edu
>Subject: Re: [plt-scheme] HTDP 21.1.2
>Date: Tue, 11 Jul 2006 09:26:19 -0400
>On Jul 11, 2006, at 8:58 AM, wooks . wrote:
>>fold is a reducing function - produces a consolidated value from  multiple 
>>inputs (eg list).
>>map is a one to one function.
>>So there is a mismatch at contract level  (hence why methinksh  trick 
>>question) .
>Its a _tricky_ question, not a trick question.
>Richard's suggestion was sound; you haven't shown us the circles you  drew 
>according to his instructions, so we can't critique your work  there, and 
>must assume that you made a mistake in the execution of  his suggestion.
>But, since you brought up contracts, lets look at the contracts for  map 
>and fold, and see if that leads us down a different path for the  solution.
>;; map : (X -> Y) [Listof X] -> [Listof Y]
>;; fold : hmm, you didn't give a contract for fold in the code you  posted 
>earlier.  Shame on you for still failing to follow the design  recipe; at 
>some point people are going to stop responding.

I am extremely appreciative of all the help I have gotten here but I wish to 
say something that  I think applies generally to people of my background.

In my first job as a trainee programmer in 1983 I was sent on a cobol 
programming course. About 2 years after this I joined a local government 
institution as a sort of "advanced trainee" and received further instruction 
in JSP.

For the benefit of anybody reading who thinks JSP stands for Java Server 
JSP (Jackson Structured Programming) is a data structure based approach to 
program design. You diagrammize your input data structures according to some 
very simple conventions then you merge the data structure diagrams  into a 
program structure. Next you list instructions needed to process the data and 
then allocate those instructions at the appropriate places on the structure 
diagram diagram. Finally you mechanically translate (again according to 
another simple convention) from the diagram, first to psuedocode and then to 
your target programming language. The diagrams and other design materials 
are retained as your program documentation. If you need to amend the program 
you work from the structure diagrams and list from the documentation you 
produced not the code- you amended structure diagrams and/or the list of 
operations or change the way they were allocated to the structure diagram 
and then  implemented the corresponding changes to the code.

I had no trouble adjusting I guess because back then  I was still in my 
programming diapers and I remeber being very receptive to it . Nonetheless 
when I graduated from the training department and was placed in one of the 
project teams I pretty soon learnt that the "real programmers" regarded that 
stuff as mumbo jumbo and didn't work that way. I remember there being a need 
  to amend a program that my team had  originally outsourced to the Training 
Department. It had come back with all the JSP parephanalia and  used  
program inversion (a technique for resolving clashes between the input data 
structures in your program) for it's print routine. Program inversion  
results in impenetrable code (at least in COBOL) so you are wholly dependent 
on the structure diagrams for its maintenance - I had been in the team long 
enough to forget how to apply the technique and was young enough to succumb 
to the peer pressure of viewing it as mumbo jumbo  so the program had to be 
sent  back to the Training Dept for amendment because "real programmers" 
couldn't amend it from the code and wouldn't read the program design 
documentation that came with it.

Needless to say that is not a situation a  Project Team Leader would want to 
be in - so do you think he  changed the programming "standards" to conform 
with J what the Training Dept did. Not a chance - rather it was the training 
school graduates who had to do the adjusting. So it was in every other 
project team and everywhere else I went - with one exception 6 years later. 
I worked at a place that  used a JSP development package - Microfocus Cobol 
Workbench. To the best of my knowledge the product has since been withdrawn 
from the marketplace and the fact that the acronym JSP has now been usurped 
for something Java related probably suggests that industries did not persist 
with its affinity for the methodology.

Although I haven't taken much persuading to adopt the design recipe I have 
yet to conceptualise how this approach to training programmers prepares them 
for maintenance work.
I don't know what the statistics are today but  a substantial part of a 
professional programmers job is maintenance  of  code that has not been 
written or maintained using a data structure oriented or  any other 
systematic approach. A project manager may take a look at an HTDPed 
candidate and rightly wonder how useful this person is going to be for all 
the maintenance work his department need to do and the thought that a person 
might try to implement design reciped induced rewrites  to all the code he's 
given to maintain will probably send a shiver up his/her spine.

If someone were to write the 10 commandments of professional software 
development 3 of them would be

Thou shalt not rely on comments in the code
Thou shalt only use  comments where the code requires clarification
There is no silver bullet development technique - Development standards are 
guidelines not mantras that must be slavishly followed.

The design recipe says otherwise. It insists that I comment every function I 
write even if like sum, length or factorial it would appear that such 
comments are superfluous from the perspective of  clarification. From what I 
have seen  as far as I have progressed so far (chap 21 of HTDP) and as is 
being reinforced to me the intent is that the mantras are slavishly 

OK - well as it happens I'm sold on it and since my university programming 
curriculum (I am now a mature student) always sets greenfield development 
project problems (as opposed to maintenance)  I get an instant return. BUT 
I've come from an environment where if you went to a colleague for help he 
would expect you to show him  code, not  comments  hence it is still my 
instinct to troubleshoot from  code. Yes I have learnt (or should I say 
relearnt) that troubleshooting from the  contracts and data structure 
documentation is extremely effective but it will take time for me to flip 
the neuron in my brain that says don't rely on comments in code. So it is 
with some of the other aspects of design recipe that contradict the habits 
of the professional programmer - I look back on some of the solutions to 
problems I have had and realise that my background programs me to not to 
consider solutions that seem to point towards repetitive computations.

When I posted the code requesting help for this problem it never occured to 
me to post the contract even (though I did write one) simply because 
AFAIwasC my code was just the equivalent of an if else statement. I did not 
see that supporting it with comments was clarifying anything - the code was 
as much clarification as anybody would need. I have not yet re-acclimated to 
the habit of using design  documentation as my primary debugging weapon. I 
instinctively think of them as comments and  2nd class citizens in the 
debugging stakes.

Thinking back to when I was being taught JSP the only challenge it presented 
to my then programming mindset was that program inversion required you to 
use lots of GOTOs in your COBOL code - but I was persuaded that the 
resulting code was just a mechanised translation of a structured technique. 
In fact it was just a higher level of programming - you were not meant to 
work from the COBOL you produced (just like you don't work from machine 
code)  but from the design documentation.

These days there are alot more neurons to flip. Sometimes my instincts are 
right - do you think I wrote blue-eyed-ancestor in chapter 14 - hell no - I 
wrote X-eyed-ancestor and parameterised the colour - in  chapter 20 I found  
baby steps codified as design recipe  for doing what I had instinctively 

So please, it is not a case of rejecting the design recipe when things don't 
appear to be all there. Some of these things are instinct others require 
some serious cranial neuron flipping. Yes I still waste far too much time 
dry running code instead of looking more closely at my design documentation. 
Alas thats the way you have to work to deal with amending  code in the "real 
world" (that phrase that programmers use to justify bad habits)  so for 
people like me it is a habit changing experience. When you are customising 
an insurance package for a client or amending a telephone companys billing 
system they are habits that you need.

>But since I want to actually put content in this post, and since you  could 
>find this information from Figure 57, I'll fill in the blank,  using the 
>argument order you gave in your post.
>;; fold : X (X Y -> Y) [Listof X] -> Y
>Now, if you look at these two contracts, they certainly look very  
>different.  map takes two arguments, fold takes three; plus, map  returns a 
>[Listof Y], while fold returns a Y.  So how could we hope  to implement map 
>in terms of fold, as you say?

Maybe I should ask the question that struck me immediately I saw this 
problem. Why would I want to do this anyway. Map and fold are clearly 
intuitive one is a translation the other is a summarisation. I cannot 
intuitively see why I would want to implement a translation in terms of a 

>The mistake in the reasoning in the preceding paragraph is the  assumption 
>that the X's and Y's in the contract for map have anything  to do with the 
>X's and Y's in the contract for fold.  Each pair of  parameters is 
>independent, implicitly quantified in each contract.   If we wanted to be 
>really formal about it, we could have written our  contracts like so:
>;; map : forall X,Y . (X -> Y) [Listof X] -> [Listof Y]
>What this is saying is that X and Y are contract parameters that, at  each 
>invocation of map, you can replace with different classes of  data.  Thus, 
>we can plug in X:=Num, Y:=String to get:
>;; map : (Num -> String) [Listof Num] -> [Listof String]
>This is often called "instantiation" or "speciailizaton" of the  contract; 
>we're taking our (very general) contract and deriving a  more specific one 
>for our particular needs at one point in the program.
>;; fold : forall X, Y . Y (X Y -> Y) [Listof X] -> Y

Well I had a more conservative
;; fold : X (X X -> X) (listof X)  ->  X

>Once again, the X's and Y's in the contract for fold are independent  from 
>the X's and Y's for map, and we could instantiate it like so:  X:=Num 
>Y:=Num to yield
>;; fold : Num (Num Num -> Num) [Listof Num] -> Num
>The names don't matter at all; in fact, we could instead use the  names S 
>and T:
>;; fold : forall S, T . T (S T -> T) [Listof S] -> T

I would more readily accept this with an example of a case where we 
summarised 2 different types of data - but lets see.

>This makes it crystal clear that the parameters for fold are totally  
>different from the ones for map.

Hmmm well all the instantation and matching stuff  looks a lot like prolog - 
but no its not crystal clear because the reason why I would want to do this 
is not intuitive.

>Now my question for you, wooks, is this:
>We have:
>;; map :  (X -> Y) [Listof X] -> [Listof Y]
>;; fold : T (S T -> T) [Listof S] -> T

>So, what class of data could you plug in for the contract parameter T  to 
>make fold return the same class of data as map?

T would have to be a list.

>When you do this  plugging in, what is the resulting instantiated contract 
>for fold?

;fold : list (S list of S -> list of S)

>  How should S be instantiated?
>(Hint: go back write the instantiation of fold for sum, product,  _and_ 
>append.  Look at the resulting classes of data.)

For sum S and product
    S is a number and T is a list of numbers.
For append S is a list  so I suppose T is a list of list?

I still don't understand how any of this helps me produce a list of the 
squares of a list of numbers.

Posted on the users mailing list.