Concepts+Techniques+and+Models+of+Computer+Programming_Part7

Concepts+Techniques+and+Models+of+Computer+Programming_Part7...

Info iconThis preview shows pages 1–3. Sign up to view the full content.

View Full Document Right Arrow Icon

Info iconThis preview has intentionally blurred sections. Sign up to view the full version.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: 138 Declarative Programming Techniques Since Ys is reduced by one element at each call, we eventually arrive at the final state S final = ( i, nil ), and the function returns i . Since length( nil ) = 0, from P ( S final ) it follows that i = length( Xs ). The difficult step in this proof is to choose the property P . It has to satisfy two constraints. First, it has to combine the arguments of the iterative computation such that the result does not change as the computation progresses. Second, it has to be strong enough that the correctness follows from P ( S final ). A rule of thumb for finding a good P is to execute the program by hand in a few small cases, and from them to picture what the general intermediate case is. Constructing programs by following the type The above examples of list functions all have a curious property. They all have a list argument, List T , which is defined as: List T ::= nil | T ´ | ´ List T and they all use a case statement which has the form: case Xs of nil then expr % Base case [] X|Xr then expr % Recursive call end What is going on here? The recursive structure of the list functions exactly follows the recursive structure of the type definition. We find that this property is almost always true of list functions. We can use this property to help us write list functions. This can be a tremen- dous help when type definitions become complicated. For example, let us write a function that counts the elements of a nested list. A nested list is a list in which each element can itself be a list, e.g., [[1 2] 4 nil [[5] 10]] . We define the type NestedList T as follows: NestedList T ::= nil | NestedList T ´ | ´ NestedList T | T ´ | ´ NestedList T To avoid ambiguity, we have to add a condition on T , namely that T is neither nil nor a cons. Now let us write the function {LengthL NestedList T }: Int which counts the number of elements in a nested list. Following the type definition gives this skeleton: fun {LengthL Xs} case Xs of nil then expr [] X|Xr andthen {IsList X} then expr % Recursive calls for X and Xr [] X|Xr then Copyright c 2001-3 by P. Van Roy and S. Haridi. All rights reserved. 3.4 Programming with recursion 139 expr % Recursive call for Xr end end (The third case does not have to mention {Not {IsList X}} since it follows from the negation of the second case.) Here {IsList X} is a function that checks whether X is nil or a cons: fun {IsCons X} case X of _|_ then true else false end end fun {IsList X} X==nil orelse {IsCons X} end Fleshing out the skeleton gives the following function: fun {LengthL Xs} case Xs of nil then [] X|Xr andthen {IsList X} then {LengthL X}+{LengthL Xr} [] X|Xr then 1+{LengthL Xr} end end Here are two example calls: X=[[1 2] 4 nil [[5] 10]] {Browse {LengthL X}} {Browse {LengthL [X X]}} What do these calls display?...
View Full Document

{[ snackBarMessage ]}

Page1 / 30

Concepts+Techniques+and+Models+of+Computer+Programming_Part7...

This preview shows document pages 1 - 3. Sign up to view the full document.

View Full Document Right Arrow Icon
Ask a homework question - tutors are online