8/7/2019 Cs.wisc Fisher Cs538 Lecture All
1/607
1CS 538 Spring 2008
CS 538
Introduction to the Theory andDesign of Programming
Languages
Charles N. Fischer
Spring 2008
http://www.cs.wisc.edu/~fischer/cs538.html
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
2/607
2CS 538 Spring 2008
Class Meets
Mondays, Wednesdays &Fridays,9:55 10:45
1325 Computer Sciences
Instructor
Charles N. Fischer
6367 Computer SciencesTelephone: 608.262.6635
E-mail: [email protected]
Office Hours:
10:30 - Noon, Tuesdays &Thursdays, or byappointment
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
3/607
3CS 538 Spring 2008
Teaching Assistant
Jongwon Yoon3361 Computer Sciences
Telephone: 608.354.3613
E-mail: [email protected]
Office Hours:2:00 - 3:00, Mondays,Wednesdays and Fridays,or by appointment
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
4/607
4CS 538 Spring 2008
Key Dates
Feb 25: Homework #1 (tentative) March 24: Programming Assignment #1 -
Scheme (tentative)
April 2: Midterm Exam (tentative)
April 16: Programming Assignment #2 -Standard ML (tentative)
May 2: Programming Assignment #3 -Prolog (tentative)
May 9: Programming Assignment #4 -Java, C#, Pizza and Python
May 15: Final Exam 2:45pm-4:45pm
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
5/607
5CS 538 Spring 2008
Class Text
Required text:Modern ProgrammingLanguages, Adam Webber,Franklin, Beedle & Associates,2003.
Handouts and Web-based reading willalso be used.
Reading Assignment Webber: Chapters 1, 10, 18
(as background)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
6/607
6CS 538 Spring 2008
Class Notes
Each lecture will be made availableprior to that lecture on the class Webpage (under the Lecture Nodes link).
Instructional Computers
Departmental Linux Machines(king01- king12, emperor01-emperor40) have beenassigned to CS 538. Allnecessary compiler,interpreters and tools will be
loaded onto these machines.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
7/607
7CS 538 Spring 2008
You may also use your own PCor laptop. It will be your
responsibility to load neededsoftware (instructions on whereto find needed software areincluded on the class webpage).
The Systems Lab teaches brieftutorials on Linux if you areunfamiliar with that OS.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
8/607
8CS 538 Spring 2008
Academic Misconduct Policy
You must do your own assignments no copying or sharing of solutions.
You may discuss general concepts andIdeas.
All cases of misconduct mustbereported to the Deans office.
Penalties may be severe.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
9/607
9CS 538 Spring 2008
Program & Homework LatePolicy
An assignment may be handed in upto 7 days late, but no later.
Each day late will be debited 4%, up toa maximum of 28%.
All students are given 10 free latedays. That is, the first 40% in latedebits will be automatically forgiven.
Your 10 free late days my be used atany time, and in any combination.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
10/607
10CS 538 Spring 2008
Approximate Grade Weights
Homework 1 10%Program 1 - Scheme 16%
Program 2 - ML 16%
Program 3 - Prolog 12%
Program 4 - Java, C#,Pizza and Python(optional extra credit) 10%
Midterm Exam 23%
Final Exam(non-cumulative) 23%
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
11/607
11CS 538 Spring 2008
Programming Languages to beConsidered in Detail
1. Scheme
A modern variant of Lisp.
A Functional Language:
Functions are first class datavalues.
Dynamically Typed:A variables type may changeduring execution; no type
declarations are needed.All memory allocation anddeallocation is automatic.
Primary data structures, listsand numbers, are unlimitedin
size and may grow withoutbound.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
12/607
12CS 538 Spring 2008
Continuationsprovide a novelway to suspend and re-
execute computations.
2. ML (Meta Language)
Strong, compile-time type
checking.Types are determined byinference rather thandeclaration.
Naturally polymorphic (one
function declaration can beused with many differenttypes).
Pattern-directed programming(you define patterns that areautomatically matched during acall).
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
13/607
13CS 538 Spring 2008
Typed exceptions are provided.
Abstract data types, withconstructors, are included.
3. Prolog (Programming in Logic)
Programs are Facts and Rules.
Programmers are concernedwith definition, not execution.
Execution order isautomatically determined.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
14/607
14CS 538 Spring 2008
4. Pizza
Extends a popular Object-
oriented language, Java, toinclude Parametric polymorphism (similar
to C++s templates).
First-class functional objects.
Algebraic data types, includingpatterns.
5. C#Microsofts answer to Java. Inmost ways it is very similar toJava, with some C++ conceptsreintroduced and some useful
additions.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
15/607
15CS 538 Spring 2008
Events and delegates are includedto handle asynchronous actions
(like keyboard or mouse actions). Properties allow user-defined read
and write actions for fields.
Indexers allow objects other thanarrays to be indexed.
Collection classes may be directlyenumerated:foreach (int i in array) ...
Structs and classes co-exist andmay be inter-converted (boxed and
unboxed). Enumerations, operator
overloading and rectangular arraysare provided.
Reference, out and variable-length
parameter lists are allowed.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
16/607
16CS 538 Spring 2008
6. Java 1.5 (Tiger Java, Java 5.0)
Extends current definition of
Java to include: Parametric polymorphism
(collection types may beparameterized).
Enhanced loop iterators.
Automatic boxing and unboxing ofwrapper classes.
Typesafe enumerations.
Static imports (out.println rather
than System.out.println). Variable argument methods.
Formatted output usingprintf:out.printf("Ans = %3d",a+b);
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
17/607
17CS 538 Spring 2008
7. Python
A simple, efficient scripting
language that quickly buildsnew programs out of existingapplications and libraries.
It cleanly includes objects.
It scales nicely into largerapplications.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
18/607
18CS 538 Spring 2008
Evolution of ProgrammingLanguages
In the beginning, ...
programs were written inabsolute machine codeasequence of bits that encode
machine instructions.Example:
34020005
0000000c
3c011001
ac220000
This form of programming is Very detailed
Very tedious
Very error-prone Very machine specific
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
19/607
19CS 538 Spring 2008
Symbolic Assemblers
Allow use of symbols foroperation codes and labels.
Example:li $v0,5
syscall
sw $v0,aFar more readable, but still verydetailed, tedious and machine-specific.
Types are machine types.
Control structures areconditional branches.
Subprograms are blocks ofcode called via a subroutine
branch instruction.All labels are global.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
20/607
20CS 538 Spring 2008
Fortran (Formula Translator)
Example:do 10 i=1,100
10 a(i)=0
Developed in the mid-50s.
A major step forward: Programming became more
problem oriented and lessmachine oriented.
Notions of control structures (ifsand do loops) were introduced.
Subprograms, calls, andparameters were made available.
Notions of machine independencewere introduced.
Has evolved into many newvariants, including Fortran 77,Fortran 90 and HPF (HighPerformance Fortran).
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
21/607
21CS 538 Spring 2008
Cobol (Common BusinessOriented Language)
Example:multiply i by 3 giving j.
move j to k.
write line1 after advancing
1 lines.
Developed in the early 60s.
The first widely-standardizedprogramming language.
Once dominant in the businessworld; still important.Wordy in structure; designedfor non-scientific users.
Raised the issue of who should
program and how importantreadability and maintainabilityare.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
22/607
22CS 538 Spring 2008
Algol 60 (Algorithmic Language)
Example:real procedure cheb(x,n);
value x,n;
real x; integer n;
cheb :=
if n = 0 then 1
else if n = 1 then xelse 2 x
cheb(x,n-1)-cheb(x,n-2);
Developed about 1960.
A direct precursor of Pascal, C,
C++ and Java.Introduced many ideas now inwide use: Blocks with local declarations and
scopes.
Nested declarations and controlstructures.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
23/607
23CS 538 Spring 2008
Parameter passing
Automatic recursion.
But, I/O wasnt standardized.
IBM promoted Fortran and PL/I.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
24/607
24CS 538 Spring 2008
Lisp (List Processing Language)
Example:((lambda (x) (* x x)) 10)
Developed in the early 60s.
A radical departure from earlierprogramming languages.
Programs and data arerepresented in a uniform listformat.
Types are a property of data
values, notvariables orparameters.
A program can build and runnew functions as it executes.
Data values were not fixed insize.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
25/607
25CS 538 Spring 2008
Memory management wasautomatic.
A formal semanticswasdeveloped to define preciselywhat a program means.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
26/607
26CS 538 Spring 2008
Simula 67 (Simulation Algol)
Example:Class Rectangle (Width, Height);Real Width, Height;
Boolean Procedure IsSquare;
IsSquare := Width=Height;
End of Rectangle;
Developed about 1967.Introduced the notion of a class(for simulation purposes).
Included objects, a garbage
collector, and notions ofextending a class.
C++ was originally C withclasses (as Simula was Algolwith classes).
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
27/607
27CS 538 Spring 2008
C and C++
C was developed in the early70s; C++ in the mid-80s.
These languages have aconcise, expressive syntax;they generate high quality code
sufficient for performance-critical applications.
C, along with Unix, proved theviability ofplatform-independentlanguages and
applications.C and C++ allow programmersa great deal of freedom inbending and breaking rules.
Raises the issue of whether onelanguage can span both noviceand expert programmers.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
28/607
28CS 538 Spring 2008
Interesting issueif moststatements and expressions are
meaningful, can errors bereadily detected?
if (a=b)
a=0;
else a = 1;
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
29/607
29CS 538 Spring 2008
Java
Developed in the late 90s.Cleaner object-orientedlanguage than C++.
Introduced notions of dynamicloading of class definitionsacross the Web.Much stronger emphasis onsecure execution and detectionof run-time errors.
Extended notions of platformindependence to systemindependence.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
30/607
30CS 538 Spring 2008
What Drives Research intoNew Programming Languages?
Why isnt C or C++ or C+++enough?
1. Curiosity
What other forms can aprogramming language take?
What other notions ofprogramming are possible?
2. Productivity
Procedural languages,including C, C++ and Java, arevery detailed.
Many source lines imply
significant development andmaintenance expenses.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
31/607
31CS 538 Spring 2008
3. Reliability
Too much low-level detail in
programs greatly enhances thechance of minor errors. Minorerrors can raise significantproblems in applications.
4. Security
Computers are entrusted withgreat responsibilities. How canwe know that a program is safeand reliable enough to trust?
5. Execution speedProcedural languages areclosely tied to the standardsequential model of instructionexecution. We may need
radically different programmingmodels to fully exploit paralleland distributed computers.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
32/607
32CS 538 Spring 2008
Desirable Qualities in aProgramming Language
Theoretically, all programminglanguages are equivalent (Why?)
If that is so, what properties aredesirable in a programming
language? It should be easy to use.
Programs should be easy to read andunderstand.
Programs should be simple to write,without subtle pitfalls.It should be orthogonal, providingonly one way to do each step orcomputation.
Its notation should be natural for the
application being programed.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
33/607
33CS 538 Spring 2008
The language should supportabstraction.
You cant anticipate all needed datastructures and operations, so addingnew definitions easily and efficientlyshould be allowed.
The language should supporttesting, debugging and
verification.
The language should have a gooddevelopment environment.
Integrated editors, compilers,debuggers, and version control are a
big plus. The language should be portable,
spanning many platforms andoperating systems.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
34/607
34CS 538 Spring 2008
The language should beinexpensive to use:
Execution should be fast.Memory needs should be modest.
Translation should be fast andmodular.
Program creation and testing should
be easy and cheap.Maintenance should not be undulycumbersome.
Components should be reusable.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
35/607
35CS 538 Spring 2008
Programming Paradigms
Programming languagesnaturally fall into a number offundamental styles orparadigms.
Procedural LanguagesMost of the widely-known andwidely-used programminglanguages (C, Fortran, Pascal,
Ada, etc.) areprocedural
.Programs execute statement bystatement, reading andmodifying a shared memory.
This programming style closely
models conventional sequentialprocessors linked to a randomaccess memory (RAM).
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
36/607
36CS 538 Spring 2008
Question:
Given
a = a + 1;
if (a > 10)
b = 10;
else b = 15;
a = a * b;
Why cant 5 processors eachexecute one line to make theprogram run 5 times faster?
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
37/607
37CS 538 Spring 2008
Functional Languages
Lisp, Scheme and ML arefunctionalin nature.Programs are expressions to beevaluated.
Language design aims to
minimize side-effects, includingassignment.
Alternative evaluationmechanisms are possible,including
Lazy (Demand Driven)
Eager (Data Driven orSpeculative)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
38/607
38CS 538 Spring 2008
Object-Oriented Languages
C++, Java, Smalltalk, Pizza andPython are object-oriented.Data and functions areencapsulated into Objects.
Objects are active, have
persistent state, and uniforminterfaces (messages ormethods).
Notions of inheritance andcommon interfaces are central.
All objects that provide thesame interface are treateduniformly. In Java you can printany object that provides thetoString method. Iteration
through the elements of anyobject that implements theEnumeration interface is possible.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
39/607
39CS 538 Spring 2008
Subclassing allows to youextend or redefine part of an
objects behavior withoutreprogramming all of theobjects definition. Thus in Java,you can take a Hashtable class(which is fairly elaborate) and
create a subclass in which anexisting method (like toString)is redefined, or new operationsare added.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
40/607
40CS 538 Spring 2008
Logic ProgrammingLanguages
Prolog notes that mostprogramming languagesaddress both the logic of aprogram (what is to be done)and its control flow (how you
do what you want).A logic programming language,like Prolog, lets programmersfocus on a programs logicwithout concern for controlissue.These languages have no realcontrol structures, and littlenotion of flow of control.
What results are programs thatare unusually succinct andfocused.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
41/607
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
42/607
42CS 538 Spring 2008
Review of Concepts fromProcedural ProgrammingLanguages
Declarations/Scope/Lifetime/Binding
Static/Dynamic Identifiers are declared, either
explicitly or implicitly (from context offirst use).
Declarations bindtype and kindinformation to an identifier. Kindspecifies the grouping of an identifier(variable, label, function, type name,etc.)
Each identifier has a scope (or range)in a programthat part of the
program in which the identifier isvisible (i.e., may be used).
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
43/607
43CS 538 Spring 2008
Data objects have a lifetimethe spanof time, during program execution,
during which the object exists andmay be used.
Lifetimes of data objects are often tiedto the scope of the identifier thatdenotes them. The objects are createdwhen its identifiers scope is entered,and they may be deleted when theidentifiers scope is exited. Forexample, memory for local variableswithin a function is usually allocatedwhen the function is called (activated)
and released when the call terminates.In Java, a method may be loaded intomemory when the object it is amember of is first accessed.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
44/607
44CS 538 Spring 2008
Properties of an identifier (and theobject it represents) may be set at Compile-time
These are staticproperties asthey do not change duringexecution. Examples includethe type of a variable, the valueof a constant, the initial valueof a variable, or the body of afunction.
Run-time
These are dynamicproperties.Examples include the value of avariable, the lifetime of a heapobject, the value of a functionsparameter, the number of times
a while loop iterates, etc.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
45/607
45CS 538 Spring 2008
Example:
In Fortran The scope of an identifier is the whole
program or subprogram.
Each identifier may be declared onlyonce.
Variable declarations may be implicit.(Using an identifier implicitly declaresit as a variable.)
The lifetime of data objects is thewhole program.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
46/607
46CS 538 Spring 2008
Block Structured Languages
Include Algol 60, Pascal, C and Java. Identifiers may have a non-global
scope. Declarations may be localto aclass, subprogram or block.
Scopes may nest, with declarations
propagating to inner (contained)scopes.
The lexically nearestdeclaration of anidentifier is bound to uses of thatidentifier.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
47/607
47CS 538 Spring 2008
Binding of an identifier to itscorresponding declaration is
usually static (also calledlexical), though dynamicbinding is also possible.
Static binding is done prior toexecutionat compile-time.
Example (drawn from C):
int x,z;void A() {
float x,y;
print(x,y,z);
}void B() {
print (x,y,z)
}
floatfloat
int
int
int
undeclared
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
48/607
48CS 538 Spring 2008
Block Structure Concepts
Nested VisibilityNo access to identifiers outsidetheir scope.
Nearest Declaration Applies
Static name scoping. Automatic Allocation and Deallocation
of Locals
Lifetime of data objects isbound to the scope of the
Identifiers that denote them.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
49/607
49CS 538 Spring 2008
Variations in these rules ofname scoping are possible.
For example, in Java, thelifetime of all class objects isfrom the time of their creation(via new) to the last visiblereference to them.
Thus
... Object O;...
creates an object reference butdoes not allocate any memory
space for O.You need
... Object O = new Object(); ...
to actually create memory
space for O.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
50/607
50CS 538 Spring 2008
Dynamic Scoping
An alternative to static scopingis dynamic scoping, which wasused in early Lisp dialects (butnot in Scheme, which isstatically scoped).
Under dynamic scoping,identifiers are bound to thedynamically closest declarationof the identifier. Thus if anidentifier is not locally
declared, the call chain(sequence of callers) isexamined to find a matchingdeclaration.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
51/607
51CS 538 Spring 2008
Example:
int x;void print() {
write(x); }
main () {
bool x;
print();}
Under static scoping the xwritten inprint is the lexicallyclosest declaration ofx, whichis as an int.Under dynamic scoping, sinceprint has no local declarationofx,prints caller is examined.
Sincemain
callsprint
, and ithas a declaration ofx as a bool,that declaration is used.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
52/607
52CS 538 Spring 2008
Dynamic scoping makes typechecking and variable access
harder and more costly thanstatic scoping. (Why?)
However, dynamic scopingdoes allow a notion of anextended scope in which
declarations extend tosubprograms called within thatscope.
Though dynamic scoping mayseen a bit bizarre, it is closelyrelated to virtual functionsused in C++ and Java.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
53/607
53CS 538 Spring 2008
Virtual Functions
A function declared in a class,C, may be redeclared in a classderived from C. Moreover, foruniformity of redeclaration, it isimportant that allcalls,
including those in methodswithin C, use the newdeclaration.
Example:class C {
void DoIt()(PrintIt();}void PrintIt(){println(C rules!);}
}class D extends C {void PrintIt()
{println(D rules!);}
void TestIt() {DoIt();}}D dvar = new D();dvar.TestIt();D rules! is printed.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
54/607
54CS 538 Spring 2008
Scope vs. Lifetime
It is usually required that thelifetime of a run-time object atleast cover the scope of theidentifier. That is, wheneveryou can access an identifier, the
run-time object it denotesbetter exist.
But,
it is possible to have a run-timeobjects lifetime exceedthe
scope of its identifier. Anexample of this is staticor ownvariables.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
55/607
55CS 538 Spring 2008
In C:
void p() {
static int i = 0;
print(i++);}
Each call top prints a differentvalue ofi (0, 1, ...) Variable i
retains its value across calls.Some languages allow anexplicit binding of an identifierfor a fixed scope:
A declaration may appear
wherever a statement orexpression is allowed. Limitedscopes enhance readability.
Let
id = valinstatements
end;
{
type id = val;statements
}
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
56/607
56CS 538 Spring 2008
Structs vs. Blocks
Many programming languages,including C, C++, C#, Pascaland Ada, have a notion ofgrouping data together intostructsor records.
For example:struct complex { float re, im; }
There is also the notion ofgrouping statements and
declarations intoblocks
:{ float re, im;re = 0.0; im = 1.0;
}
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
57/607
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
58/607
58CS 538 Spring 2008
Blocks are code, They can contain both code and
data. Blocks cantbe dynamically created
during execution; they are builtinto a program.
Locals in a block arentvisible
outside the block.By adding functions andinitialization code to structs,we get classesa nice blend ofstructs and blocks.
For example:
class complex{
float re, im;
complex (float v1, float v2){
re = v1; im = v2; }}
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
59/607
59CS 538 Spring 2008
Classes
Class objects can be created asneeded, in any number, and includedin other data structure.
They include both data (fields) andfunctions (methods).
They include mechanisms to initializethemselves (constructors) and tofinalize themselves (destructors).
They allow controlled access tomembers (private and publicdeclarations).
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
60/607
60CS 538 Spring 2008
Type Equivalence in Classes
In C, C++ and Java, instances ofthe same struct or class aretype-equivalent, and mutuallyassignable.
For example:
class MyClass { ... }MyClass v1, v2;v1 = v2; // Assignment is OK
We expect to be able to assignvalues of the same type,including class objects.
However, sometimes a classmodels a data object whose
size or shape is set uponcreation (in a constructor).
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
61/607
61CS 538 Spring 2008
Then we may notwantassignment to be allowed.
class Point {int dimensions;float coordinates[];Point () {dimensions = 2;
coordinates = new float[2];}
Point (int d) {dimensions = d;coordinates = new float[d];
}}
Point plane = new Point();Point solid = new Point(3);
plane = solid; //OK in Java
This assignment is allowed,
even though the two objectsrepresent points in differentdimensions.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
62/607
62CS 538 Spring 2008
Subtypes
In C++, C# and Java we cancreate subclassesnew classesderived from an existing class.
We can use subclasses to createnew data objects that are
similar (since they are based ona common parent), but stilltype-inequivalent.
Example:
class Point2 extends Point {
Point2() {super(2); }
}
class Point3 extends Point {
Point3() {super(3); }
}
Point2 plane = new Point2();Point3 solid = new Point3();
plane = solid; //Illegal in Java
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
63/607
63CS 538 Spring 2008
Parametric Polymorphism
We can create distinctsubclasses based on the valuespassed to constructors. Butsometimes we want to createsubclasses based on distinct
types, and types cant bepassed as parameters. (Typesare not values, but rather aproperty of values.)
We see this problem in Java,
which tries to create generalpurpose data structures bybasing them on the classObject. Since any object can beassigned to Object (all classes
must be a subclass ofObject),this worksat least partially.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
64/607
64CS 538 Spring 2008
class LinkedList {
Object value;LinkedList next;
Object head() {return value;}
LinkedList tail(){return next;}
LinkedList(Object O) {value = O; next = null;}
LinkedList(Object O,
LinkedList L){value = O; next = L;}}
Using this class, we can createa linked list of any subtype ofObject.
But, We cant guarantee that linked lists
are type homogeneous(containonly a single type).
We must cast Object types backinto their real types when weextract list values.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
65/607
65CS 538 Spring 2008
We must use wrapper classes likeInteger rather than int (because
primitive types like int arentobjects, and arent subclass ofObject).
For example, to use LinkedListto build a linked list ofints we
do the following:LinkedList l =new LinkedList(new Integer(123));
int i =((Integer) l.head()).intValue();
This is pretty clumsy code.Wed prefer a mechanism thatallows us to create a customversion ofLinkedList, basedon the type we want the list tocontain.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
66/607
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
67/607
67CS 538 Spring 2008
Thus we haveclass LinkedList {
T value; LinkedList next;T head() {return value;}
LinkedList tail() {return next;}
LinkedList(T O) {value = O; next = null;}
LinkedList(T O,LinkedList L)
{value = O; next = L;}}
LinkedList l =new LinkedList(123);
int i = l.head();
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
68/607
68CS 538 Spring 2008
Overloading and Ad-hocPolymorphism
Classes usually allowoverloading of method names,if only to support multipleconstructors.
That is, more than one methoddefinition with the same nameis allowed within a class, aslong as the method definitionsdiffer in the number and/or
types of the parameters theytake.
For example,class MyClass {
int f(int i) { ... }
int f(float g) { ... }int f(int i, int j) { ... }
}
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
69/607
69CS 538 Spring 2008
Overloading is sometimescalled ad hoc polymorphism,
because, to the programmer, itappears that one method cantake a variety of differentparameter types. This isnt truepolymorphism because the
methods have different bodies;there is no sharing of onedefinition among differentparameter types. There is noguarantee that the different
definitions do the same thing,even though they share acommon name.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
70/607
70CS 538 Spring 2008
Issues in Overloading
Though many languages allowoverloading, few allowoverloaded methods to differonly on their result types.(Neither C++ nor Java allow this
kind of overloading, thoughAda does). For example,class MyClass {
int f() { ... }
float f() { ... }
}
is illegal. This is unfortunate;methods with the same nameand parameters, but differentresult types, could be used to
automatically convert resultvalues to the type demandedby the context of call.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
71/607
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
72/607
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
73/607
73CS 538 Spring 2008
The expression 10+c is illegalbecause there is no definition
of+ for the types int andMyClass&. We can create one byusing C++s friendmechanismto insert a definition intoMyClass that will have access to
MyClasss private data:class MyClass {
int i;
public:
int operator+(int j) {
return i+j; }friend int operator+(int j, MyClass& v){
return j+v.i; }
}
MyClass c;
int k = 10+c; // Now OK!
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
74/607
74CS 538 Spring 2008
C++ limits operator overloadingto existing predefined operators.
A few languages, like Algol 68 (asuccessor to Algol 60, developedin 1968), allow programmers todefine brand new operators.
In addition to defining theoperator itself, it is also necessaryto specify the operatorsprecedence (which operator is tobe applied first) and itsassociativity (does the operatorassociate from left to right, or
right to left, or not at all). Giventhis extra detail, it is possible tospecify something like
op +++ prec = 8;int op +++(int& i, int& j) {return (i++)+(j++); }
(Why is int& used as theparameter type rather than int?)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
75/607
75CS 538 Spring 2008
Parameter Binding
Almost all programminglanguages have some notion ofbindingan actual parameter(provided at the point of call) to aformal parameter(used in thebody of a subprogram).
There are many different, andinequivalent, methods ofparameter binding. Exactly whichis used depends upon theprogramming language in
question.Parameter Binding Modes include:
Value: The formal parameterrepresents a local variableinitialized to the value of the
corresponding actual parameter.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
76/607
76CS 538 Spring 2008
Result: The formal parameterrepresents a local variable. Its final
value, at the point of return, iscopied into the correspondingactual parameter.
Value/Result: A combination of thevalue and results modes. Theformal parameter is a local variableinitialized to the value of thecorresponding actual parameter.The formals final value, at thepoint of return, is copied into thecorresponding actual parameter.
Reference: The formal parameter isa pointer to the correspondingactual parameter. All references tothe formal parameter indirectlyaccess the corresponding actualparameter through the pointer.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
77/607
77CS 538 Spring 2008
Name: The formal parameterrepresents a block of code
(sometimes called a thunk) that isevaluated to obtain the value oraddress of the correspondingactual parameter. Each reference tothe formal parameter causes thethunk to be reevaluated.
Readonly (sometimes called Const):Only reads of the formal parameterare allowed. Either a copy of theactual parameters value, or itsaddress, may be used.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
78/607
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
79/607
79CS 538 Spring 2008
Example
void p(value int a,reference int b,
name int c) {
a=1; b=2; print(c)
}
int i=3, j=3, k[10][10];
p(i,j,k[i][j]);
What element ofk is printed? The assignment to a does not
affect i, since a is a value
parameter. The assignment to b doesaffect j,
since b is a reference parameter.
c is a name parameter, so it isevaluated whenever it is used. In
the print statement k[i][j] isprinted. At that point i=3 and j=2,so k[3][2] is printed.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
80/607
80CS 538 Spring 2008
Why are there so ManyDifferent Parameter Modes?
Parameter modes reflectdifferent views on howparameters are to be accessed,as well as different degrees of
efficiency in accessing andusing parameters. Call by value protectsthe actual
parameter value. No matter whatthe subprogram does, the
parameter cantbe changed. Call by reference allows immediate
updates to the actual parameter.
Call by readonly protects the actualparameter and emphasizes the
constant nature of the formalparameter.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
81/607
81CS 538 Spring 2008
Call by value/result allows actualparameters to change, but treats a
call as a single step (assignparameter values, execute thesubprograms body, updateparameter values).
Call by name delays evaluation ofan actual parameter until it isactually needed (which may benever).
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
82/607
82CS 538 Spring 2008
Call by Name
Call by name is a special kindof parameter passing mode. Itallows some calls to completethat otherwise would fail.Consider
f(i,j/0)Normally, when j/0 isevaluated, a divide faultterminates execution. Ifj/0 ispassed by name, the division is
delayed until the parameter isneeded, which may be never.
Call by name also allowsprogrammers to create someinteresting solutions to hardprogramming problems.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
83/607
83CS 538 Spring 2008
Consider the conditionalexpression found in C, C++,
and Java:(cond ? value1 : value2)
What if we want to implementthis as a function call:
condExpr(cond,value1,value2) {if (cond)
return value1;
else return value2;
}
With most parameter passingmodes this implementationwont work! (Why?)
But ifvalue1 andvalue2 arepassed by name, the
implementation is correct.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
84/607
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
85/607
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
86/607
86CS 538 Spring 2008
The whole list is there, but only asmuch as you care to access is
actually computed.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
87/607
87CS 538 Spring 2008
Eager Parameter Evaluation
Sometimes we want parametersevaluated eagerlyas soon asthey are known.
Consider a sorting routine thatbreaks an array in half, sorts
each half, and then mergestogether the two sorted halves(this is a merge sort).
In outline form it is:sort(inputArray) {
...merge(sort(leftHalf(inputArray)),
sort(rightHalf(inputArray)));}
This definition lends itselfnicely to parallel evaluation:
The two halves of an inputarray can be sorted in parallel.Each of these two halves can
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
88/607
88CS 538 Spring 2008
again be split in two, allowingparallel sorting of four quarter-
sized arrays, then leading to 8sorts of 1/8 sized arrays, etc.
But,to make this all work, the twoparameters to merge must be
evaluated eagerly, rather thanin sequence.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
89/607
89CS 538 Spring 2008
Type Equivalence
Programming languages usetypes to describe the values adata object may hold and theoperations that may beperformed.
By checking the types of values,potential errors in expressions,assignments and calls may beautomatically detected. Forexample, type checking tells usthat
123 + "123"is illegal because addition is notdefined for an integer, stringcombination.
Type checking is usually done at
compile-time; this is static typing.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
90/607
90CS 538 Spring 2008
Type-checking may also be doneat run-time; this is dynamic
typing.A program is type-safe if it isimpossible to apply an operationto a value of the wrong type. In atype-safe language, plus is nevertold to add an integer to a string,because its definition does notallow that combination ofoperands. In type-safe programsan operator can still see an illegalvalue (e.g., a division by zero),
but it cant see operands of thewrong type.
A strongly-typedprogramminglanguage forbids the execution oftype-unsafe programs.
Weakly-typedprogramminglanguages allow the execution ofpotentially type-unsafe programs.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
91/607
91CS 538 Spring 2008
The question reduces to whetherthe programming language allows
programmers to break the typerules, either knowingly orunknowingly.
Java is strongly typed; type errorspreclude execution. C and C++are weakly typed; you can breakthe rules if you wish. Forexample:
int i; int* p;
p = (int *) i * i;
Nowp may be used as an integerpointer though multiplicationneed not produce valid integerpointers.
If we are going to do typechecking in a program, we must
decide whether two types, T1 andT2 are equivalent; that is, whetherthey be used interchangeably.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
92/607
92CS 538 Spring 2008
There are two major approachesto type equivalence:
Name Equivalence:Two types are equivalent if andonly if they refer to exactly thesame type declaration.
For example,
type PackerSalaries = int[100];type AssemblySizes = int[100];PackerSalaries salary;AssemblySizes size;
Is
sal = size;allowed?
Using name equivalence, no. Thatis, salary /N size since thesetwo variables have different type
declarations (that happen to beidentical in structure).
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
93/607
93CS 538 Spring 2008
Formally, we define N (name typeequivalence) as:
(a) T N T(b) Given the declaration
Type T1 = T2;
T1 N T2
We treat anonymous types (typesnot given a name) as anabbreviation for an implicitdeclaration of a new and unique
type name.Thusint A[10];
is an abbreviation for
Type Tnew= int[10];
Tnew A;
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
94/607
94CS 538 Spring 2008
Structural Equivalence
An alternative notion of typeequivalence is structuralequivalence (denoted S).Roughly, two types arestructurally equivalent if the twotypes have the same definition,independent of where thedefinitions are located. That is,the two types have the samedefinitional structure.
Formally,
(a) T S T(b) Given the declaration
Type T = Q;
T S Q
(c) If T and Q are defined usingthe same type constructor andcorresponding parameters in the
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
95/607
95CS 538 Spring 2008
two definitions are equal orstructurally equivalent
then T S Q
Returning to our previousexample,type PackerSalaries = int[100];
type AssemblySizes = int[100];
PackerSalaries salary;
AssemblySizes size;
salary Ssize since both are
arrays and 100=100 and int Sint.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
96/607
96CS 538 Spring 2008
Which notion of Equivalence doProgramming Languages Use?
C and C++ use structuralequivalence except for structsand classes (where nameequivalence is used). For arrays,size is ignored.
Java uses structural equivalencefor scalars. For arrays, it requiresname equivalence for thecomponent type, ignoring size.For classes it uses name
equivalence except that a subtypemay be used where a parent typeis expected. Thus givenvoid subr(Object O) { ... };
the call
subr(new Integer(100));is OK since Integer is a subclass ofObject.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
97/607
97CS 538 Spring 2008
Automatic Type Conversions
C, C++ and Java also allow variouskinds of automatic typeconversions.
In C, C++ and Java, a float willbe automatically created from anint:
float f = 10; // No type error
Also, an integer type (char,short, int, long) will bewidened:int i = 'x';
In C and C++ (but not Java), aninteger value can also benarrowed, possibly with the lossof significant bits:char c = 1000000;
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
98/607
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
99/607
99CS 538 Spring 2008
Lisp & Scheme
Lisp (List Processing Language)is one of the oldestprogramming languages still inwide use.
It was developed in the late 50s
and early 60s by JohnMcCarthy.
Its innovations include: Support of symbolic computations.
A functional programming stylewithout emphasis on assignmentsand side-effects.
A naturally recursive programmingstyle.
Dynamic (run-time) type checking.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
100/607
100CS 538 Spring 2008
Dynamic data structures (lists,binary trees) that grow without
limit. Automatic garbage collection to
manage memory.
Functions are treated as first classvalues; they may be passed as
arguments, returned as resultvalues, stored in data structures,and created during execution.
A formal semantics (written in Lisp)that defines the meaning of allvalid programs.
An Integrated ProgrammingEnvironment to create, edit andtest Lisp programs.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
101/607
101CS 538 Spring 2008
Scheme
Scheme is a recent dialect ofLisp.
It uses lexical (static) scoping.
It supports true first-classfunctions.
It provides program-levelaccess to control flow viacontinuation functions.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
102/607
102CS 538 Spring 2008
Atomic (Primitive) Data Types
Symbols:Essentially the same form asidentifiers. Similar to enumerationvalues in C and C++.
Very flexible in structure;
essentially any sequence ofprintable characters is allowed;anything that starts a validnumber (except + or -) may notstart a symbol.
Valid symbols include:abc hello-world +
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
103/607
103CS 538 Spring 2008
Reals:
A floating point number in a
decimal format (123.456) or inexponential format (1.23e45). Aleading sign and a signedexponent are allowed(-12.3, 10.0e-20).
Rationals:Rational numbers of the forminteger/integer (e.g., 1/3 or 9/7)with an optional leading sign (-1/2, +7/8).
Complex:Complex numbers of the formnum+num i or num-num i, wherenum is an integer or real number.Example include 1+3i, -1.5-2.5i, 0+1i).
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
104/607
104CS 538 Spring 2008
String:
A sequence of characters
delimited by double quotes.Double quotes and backslashesmust be escaped using abackslash. For example
"Hello World" "\"Wow!\""
Character:A single character prefixed by #\.For example, #\a, #\0, #\\, #\#.Two special characters are#\space and #\newline.
Boolean:
True is represented as #t andfalse is represented as #f.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
105/607
105CS 538 Spring 2008
Binary Trees
Binary trees are also calledS-Expressionsin Lisp and Scheme.
They are of the form
( item . item )
where item is any atomic value or
any S-Expression. For example:( A . B )(1.2 . "xyz" )( (A . B ) . C )( A . (B . C ) )
S-Expressions are linearizations ofbinary trees:
A B 1.2 "xyz"
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
106/607
106CS 538 Spring 2008
S-Expressions are built and
accessed using the predefinedfunctions cons, carand cdr.
cons builds a new S-Expressionfrom two S-Expressions thatrepresent the left and rightchildren.
cons(E1,E2) = (E1 . E2)
car returns are left subtree of anS-Expression.
car (E1 . E2) = E1
cdr returns are right subtree of anS-Expression.
cdr (E1 . E2) = E2
C A
A B B C
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
107/607
107CS 538 Spring 2008
Lists
In Lisp and Scheme lists are aspecial, widely-used form of S-Expressions.() represents the empty or null list(A) is the list containingA.By definition, (A) (A . () )
(A B) represents the listcontainingAand B. By definition,(A B) (A . (B . () ) )
In general, (A B C ... Z)
(A . (B . (C . ... (Z . () ) ... )))
(A B C )
A
B
C ()
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
108/607
108CS 538 Spring 2008
Function Calls
In List and Scheme, function callsare represented as lists.
(A B C) means:
EvaluateA(to a function)
Evaluate B and C (as parameters)
CallAwith B and C as itsparameters
Use the value returned by the callas the meaning of(A B C).
cons, car and cdr are predefined
symbols bound to built-infunctions that build and accesslists and S-Expressions.
Literals (of type integer, real,rational, complex, string,
character and boolean) evaluateto themselves.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
109/607
109CS 538 Spring 2008
For example ( means evaluatesto)
(cons 1 2) (1 . 2)
(cons 1 () ) (1)
(car (cons 1 2)) 1
(cdr (cons 1 ())) ()
But,(car (1 2)) fails during
execution!
Why?
The expression (1 2) looks like acall, but 1 isnt a function! Weneed some way to quotesymbols and lists we dontwantevaluated.(quote arg)
is a special function that returnsits argument unevaluated.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
110/607
110CS 538 Spring 2008
Thus (quote (1 2)) doesnt tryto evaluate the list (1 2); it just
returns it.Since quotation is so often used,it may be abbreviated using asingle quote. That is
(quote arg) 'arg
Thus(car '(a b c)) a
(cdr '( (A) (B) (C))) ( (B) (C) )
(cons 'a '1) (a . 1)But,
('cdr '(A B)) fails!
Why?
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
111/607
111CS 538 Spring 2008
User-defined Functions
The list(lambda (args) (body))
evaluates to a function with(args) as its argument list and(body) as the function body.
No quotes are needed for(args) or (body).
Thus
(lambda (x) (+ x 1)) evaluates
to the increment function.Similarly,
((lambda (x) (+ x 1)) 10) 11
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
112/607
112CS 538 Spring 2008
We can bind values andfunctions to global symbols
using the define function.The general form is
(define id object)
id is not evaluated but object
is. id is bound to the valueobject evaluates to.
For example,
(define pi 3.1415926535)
(define plus1(lambda (x) (+ x 1)) )
(define pi*2 (* pi 2))
Once a symbol is defined, itevaluates to the value it is
bound to:(plus1 12) 13
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
113/607
113CS 538 Spring 2008
Since functions are frequentlydefined, we may abbreviate
(define id(lambda (args) (body)) )
as(define (id args) (body) )
Thus
(define (plus1 x) (+ x 1))
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
114/607
114CS 538 Spring 2008
Conditional Expressions inScheme
A predicate is a function thatreturns a boolean value. Byconvention, in Scheme, predicatenames end with ?
For example,number? symbol? equal?null? list?
In conditionals, #f is false, andeverything else, including #t, istrue.
The if expression is(if pred E1 E2)
Firstpred is evaluated.Depending on its value (#f ornot), either E1 or E2 is evaluated(but not both) and returned as thevalue of the if expression.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
115/607
115CS 538 Spring 2008
For example,(if (= 1 (+ 0 1))
'Yes'No
)
(define
(fact n)(if (= n 0)
1
(* n (fact (- n 1))))
)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
116/607
116CS 538 Spring 2008
Generalized Conditional
This is similar to a switch or case:(cond(p1 e1)
(p2 e2)
...
(else en)
)
Each of the predicates (p1,p2, ...)is evaluated until one is true (#f). Then the correspondingexpression (e1, e2, ...) is
evaluated and returned as thevalue of the cond. else acts like apredicate that is always true.
Example:
(cond
((= a 1) 2)((= a 2) 3)(else 4)
)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
117/607
117CS 538 Spring 2008
Recursion in Scheme
Recursion is widely used inScheme and most other functionalprogramming languages.
Rather than using a loop to stepthrough the elements of a list orarray, recursion breaks a problemon a large data structure into asimpler problem on a smaller datastructure.
A good example of this approachis the append function, which
joins (or appends) two lists intoone larger list containing all theelements of the two input lists (inthe correct order).
Note that cons is notappend.
cons adds one element to thehead of an existing list.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
118/607
118CS 538 Spring 2008
Thus(cons '(a b) '(c d))
((a b) c d)(append '(a b) '(c d)) (a b c d)
The append function is predefinedin Scheme, as are many otheruseful list-manipulating functions
(consult the Scheme definition forwhats available).
It is instructive to define appenddirectly to see its recursiveapproach:
(define(append L1 L2)(if (null? L1)
L2(cons (car L1)
(append (cdr L1) L2)))
)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
119/607
119CS 538 Spring 2008
Lets trace (append '(a b) '(c d))Our definition is
(define(append L1 L2)(if (null? L1)
L2(cons (car L1)
(append (cdr L1) L2)))
)
Now L1 = (a b) and L2 = (c d).
(null? L1) is false, so weevaluate(cons (car L1) (append (cdr L1) L2))
= (cons (car '(a b))(append (cdr '(a b)) '(c d)))= (cons 'a (append '(b) '(c d))
We need to evaluate(append '(b) '(c d))
In this call, L1 = (b) and L2 = (c d).
L1 is not null, so we evaluate
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
120/607
120CS 538 Spring 2008
(cons (car L1) (append (cdr L1) L2))= (cons (car '(b))
(append (cdr '(b)) '(c d)))
= (cons 'b (append '() '(c d))
We need to evaluate(append '() '(c d))
In this call, L1 = () and L2 = (c d).
L1 is null, so we return (c d).
Therefore(cons 'b (append '() '(c d)) =(cons 'b '(c d)) = (b c d) =(append '(b) '(c d))
Finally,(append '(a b) '(c d)) =(cons 'a (append '(b) '(c d)) =
(cons 'a '(b c d)) = (a b c d)
Note:
Source files for append, and other
Scheme examples, are in~cs538-1/public/scheme/example1.scm,~cs538-1/public/scheme/example2.scm,etc.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
121/607
121CS 538 Spring 2008
Reversing a List
Another useful list-manipulationfunction is rev, which reversesthe members of a list. That is, thelast element becomes the firstelement, the next-to-last elementbecomes the second element, etc.
For example,(rev '(1 2 3)) (3 2 1)
The definition ofrev isstraightforward:(define (rev L)(if (null? L)
L(append (rev (cdr L))
(list (car L))
))
)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
122/607
122CS 538 Spring 2008
As an example, consider(rev '(1 2))
Here L = (1 2). L is not null so weevaluate(append (rev (cdr L))
(list (car L))) =
(append (rev (cdr '(1 2)))(list (car '(1 2)))) =
(append (rev '(2)) (list 1)) =(append (rev '(2)) '(1))
We must evaluate (rev '(2))
Here L = (2). L is not null so weevaluate(append (rev (cdr L))
(list (car L))) =
(append (rev (cdr '(2)))(list (car '(2)))) =
(append (rev ())(list 2)) =(append (rev ())'(2))
We must evaluate (rev '())
Here L = (). L is null so(rev '())= ()
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
123/607
123CS 538 Spring 2008
Thus (append (rev ())'(2)) =(append () '(2)) = (2) = (rev '(2))
Finally, recall (rev '(1 2)) =(append (rev '(2)) '(1)) =(append '(2) '(1)) = (2 1)
As constructed, rev only reversesthe top level elements of a list.That is, members of a list thatthemselves are lists arentreversed.
For example,(rev '( (1 2) (3 4))) =((3 4) (1 2))
We can generalize rev to alsoreverse list members that happento be lists.
To do this, it will be convenient touse Schemes let construct.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
124/607
124CS 538 Spring 2008
The Let Construct
Scheme allows us to create localnames, bound to values, for usein an expression.
The structure is(let ( (id1 val1) (id2 val2) ... )expr )
In this construct,val1 isevaluated and bound to id1,which will exist only within thislet expression. Ifid1 is alreadydefined (as a global or parameter
name) the existing definition ishidden and the local definition,bound toval1, is used. Thenval2 is evaluated and bound toid2, .... Finally, expr is evaluatedin a scope that includes id1, id2,
...
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
125/607
125CS 538 Spring 2008
For example,(let ( (a 10) (b 20) )
(+ a b)) 30
Using a let, the definition ofrevall, a version ofrev thatreverses all levels of a list, is easy:
(define (revall L)
(if (null? L)L(let ((E (if (list? (car L))
(revall (car L))(car L) )))
(append (revall (cdr L))(list E))
)
))
(revall '( (1 2) (3 4)))
((4 3) (2 1))
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
126/607
126CS 538 Spring 2008
Subsets
Another good example ofSchemes recursive style ofprogramming is subsetcomputation.
Given a list of distinct atoms, wewant to compute a list of allsubsets of the list values.For example,
(subsets '(1 2 3))
( () (1) (2) (3) (1 2) (1 3)(2 3) (1 2 3))
The order of atoms and sublists isunimportant, but all possiblesubsets of the list values must beincluded.
Given Schemes recursive style of
programming, we need arecursive definition of subsets.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
127/607
127CS 538 Spring 2008
That is, if we have a list of allsubsets of n atoms, how do we
extend this list to one containingall subsets of n+1 values?
First, we note that the number ofsubsets of n+1 values is exactlytwice the number of subsets of nvalues.
For example,
(subsets '(1 2) )
( () (1) (2) (1 2)), whichcontains 4 subsets.
(subsets '(1 2 3)) contains 8subsets (as we saw earlier).
Moreover, the extended list (ofsubsets for n+1 values) is simplythe list of subsets for n valuesplusthe result of distributingthe new value into each of theoriginal subsets.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
128/607
128CS 538 Spring 2008
Thus (subsets '(1 2 3)) ( () (1) (2) (3) (1 2) (1 3)
(2 3) (1 2 3)) =( () (1) (2) (1 2) ) plus
( (3) (1 3) (2 3) (1 2 3) )
This insight leads to a conciseprogram for subsets.
We will let (distrib L E) be afunction that distributes E intoeach list in L.
For example,
(distrib '(() (1) (2) (1 2)) 3) =
( (3) (3 1) (3 2) (3 1 2) )(define (distrib L E)
(if (null? L)
()
(cons (cons E (car L))
(distrib (cdr L) E))
))
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
129/607
129CS 538 Spring 2008
We will let (extend L E) extend alist L by distributing element E
through L and then appendingthis result to L.
For example,
(extend '( () (a) ) 'b)
( () (a) (b) (b a))
(define (extend L E)
(append L (distrib L E))
)
Now subsets is easy:
(define (subsets L)
(if (null? L)
(list ())
(extend (subsets (cdr L))(car L))
))
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
130/607
130CS 538 Spring 2008
Data Structures in Scheme
In Scheme, lists and S-expressionsare basic. Arrays can be simulatedusing lists, but access to elementsdeep in the list can be slow(since a list is a linked structure).
To access an element deep withina list we can use: (list-tail L k)
This returns list L after removingthe first k elements. For example,(list-tail '(1 2 3 4 5) 2)
(3 4 5)
(list-ref L k)This returns the k-th element in L(counting from 0). For example,(list-ref '(1 2 3 4 5) 2) 3
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
131/607
131CS 538 Spring 2008
Vectors in Scheme
Scheme provides a vector typethat directly implements onedimensional arrays.
Literals are of the form #( ... )
For example, #(1 2 3) or
#(1 2.0 "three")The function (vector? val)tests whetherval is a vector ornot.
(vector? 'abc) #f
(vector? '(a b c)) #f
(vector? #(a b c)) #t
The function (vector v1 v2
...) evaluatesv1,v2, ... and putsthem into a vector.
(vector 1 2 3) #(1 2 3)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
132/607
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
133/607
133CS 538 Spring 2008
For example,(define v #(1 2 3 4 5))
(vector-set! v 2 0)v #(1 2 0 4 5)
Vectors arentlists (and listsarentvectors).
Thus (car #(1 2 3)) doesnt
work.There are conversion routines:
(vector->list V) convertsvectorVto a list containing thesame values asV. For example,
(vector->list #(1 2 3)) (1 2 3)
(list->vector L) converts list Lto a vector containing the samevalues as L. For example,
(list->vector '(1 2 3))
#(1 2 3)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
134/607
134CS 538 Spring 2008
In general Scheme names aconversion function from type T to
type Q as T->Q. For example,string->list converts a stringinto a list containing thecharacters in the string.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
135/607
135CS 538 Spring 2008
Records and Structs
In Scheme we can represent arecord, struct, or class object asan association listof the form((obj1 val1) (obj2 val2) ...)
In the association list, which is alist of(object value) sublists,object serves as a key to locatethe desired sublist.
For example, the association list( (A 10) (B 20) (C 30) )
serves the same role asstruct{ int a = 10;int b = 20;int c = 30;}
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
136/607
136CS 538 Spring 2008
The predefined Scheme function(assoc obj alist)
checks alist (an association list)to see if it contains a sublist withobj as its head. If it does, the liststarting with obj is returned;otherwise #f (indicating failure) is
returned.For example,(define L'( (a 10) (b 20) (c 30) ) )
(assoc 'a L) (a 10)
(assoc 'b L)
(b 20)(assoc 'x L) #f
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
137/607
137CS 538 Spring 2008
We can use non-atomic objects askeys too!
(define price-list'( ((bmw m5) 71095)
((bmw z4) 40495)
((jag xj8) 56975)
((mb sl500) 86655)
))
(assoc '(bmw z4) price-list) ((bmw z4) 40495)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
138/607
138CS 538 Spring 2008
Using assoc, we can easily definea structure function:
(structure key alist) willreturn the value associated withkey in alist; in C or Javanotation, it returns alist.key.(define
(structure key alist)(if (assoc key alist)
(car (cdr (assoc key alist)))
#f
))
We can improve this function intwo ways:
The same call to assoc is madetwice; we can save the valuecomputed by using a let
expression. Often combinations ofcar and cdr
are needed to extract a value.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
139/607
139CS 538 Spring 2008
Scheme has a number ofpredefined functions that combine
several calls to car and cdr intoone function. For example,(caar x) (car (car x))
(cadr x) (car (cdr x))
(cdar x) (cdr (car x))
(cddr x)
(cdr (cdr x))
Using these two insights we cannow define a better version ofstructure
(define
(structure key alist)(let ((p (assoc key alist)))
(if p
(cadr p)
#f
)
)
)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
140/607
140CS 538 Spring 2008
What does assoc do if more thanone sublist with the same key
exists?It returns the first sublist with amatching key. In fact, thisproperty can be used to make asimple and fast function thatupdates association lists:(define(set-structure key alist val)(cons (list key val) alist)
)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
141/607
141CS 538 Spring 2008
If we want to be more space-efficient, we can create a version
that updates the internal structureof an association list, usingset-cdr! which changes the cdrvalue of a list:(define(set-structure! key alist val)
(let ( (p (assoc key alist)))(if p
(begin
(set-cdr! p (list val))
alist
)(cons (list key val) alist)
)
)
)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
142/607
142CS 538 Spring 2008
Functions are First-classObjects
Functions may be passed asparameters, returned as the valueof a function call, stored in dataobjects, etc.
This is a consequence of the factthat
(lambda (args) (body))
evaluates to a function just as
(+ 1 1)
evaluates to an integer.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
143/607
143CS 538 Spring 2008
Scoping
In Scheme scoping is static(lexical). This means that non-local identifiers are bound tocontaining lambda parameters, orlet values, or globally definedvalues. For example,
(define (f x)(lambda (y) (+ x y)))
Function f takes one parameter,x. It returns a function (ofy), withx in the returned function bound
to the value ofx used when f wascalled.
Thus
(f 10) (lambda (y) (+ 10 y))
((f 10) 12) 22
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
144/607
144CS 538 Spring 2008
Unbound symbols are assumed tobe globals; there is a run-time
error if an unbound global isreferenced. For example,(define (p y) (+ x y))
(p 20) ; error -- x is unbound
(define x 10)
(p 20) 30We can use let bindings to createprivate local variables forfunctions:(define F
(let ( (X 1) )(lambda () X)
))
F is a function (of no arguments).
(F) calls F.(define X 22)
(F) 1;X used in F is private
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
145/607
145CS 538 Spring 2008
We can encapsulate internal statewith a function by using private,
let-bound variables:(define cnt(let ( (I 0) )
(lambda ()
(set! I (+ I 1)) I))
)
Now,
(cnt) 1
(cnt) 2
(cnt) 3
etc.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
146/607
146CS 538 Spring 2008
Let Bindings can be Subtle
You must check to see if the let-bound value is created when thefunction is createdor when it iscalled.
Compare
(define cnt(let ( (I 0) )
(lambda ()
(set! I (+ I 1)) I))
)
vs.(define reset(lambda ()
(let ( (I 0) )
(set! I (+ I 1)) I))
)(reset) 1, (reset) 1, etc.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
147/607
147CS 538 Spring 2008
Simulating Class Objects
Using association lists and privatebound values, we can encapsulatedata and functions. This gives usthe effect of class objects.(define (point x y)(list
(list 'rect(lambda () (list x y)))
(list 'polar(lambda ()(list(sqrt (+ (* x x) (* y y)))(atan (/ x y)))
))
))
A call (point 1 1) creates an
association list of the form( (rect funct) (polar funct) )
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
148/607
148CS 538 Spring 2008
We can use structure to accesscomponents:
(define p (point 1 1) )( (structure 'rect p) ) (1 1)
( (structure 'polar p) )
( )2
4---
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
149/607
149CS 538 Spring 2008
We can add new functionality byjust adding new (id function)
pairs to the association list.(define (point x y)(list(list 'rect
(lambda () (list x y)))(list 'polar
(lambda ()
(list(sqrt (+ (* x x) (* y y)))(atan (/ x y))
)))(list 'set-rect!
(lambda (newx newy)(set! x newx)
(set! y newy)(list x y)
))(list 'set-polar!
(lambda (r theta)(set! x (* r (sin theta)))(set! y (* r (cos theta)))
(list r theta)))
))
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
150/607
150CS 538 Spring 2008
Now we have(define p (point 1 1) )
( (structure 'rect p) ) (1 1)( (structure 'polar p) )
( )
((structure 'set-polar! p) 1 /4) (1 /4)
( (structure 'rect p) )
( )
2
4---
1
2
-------
1
2
-------
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
151/607
151CS 538 Spring 2008
Limiting Access to InternalStructure
We can improve upon ourassociation list approach byreturning a single function(similar to a C++ or Java object)rather than an explicit list of (idfunction) pairs.The function will take the name ofthe desired operation as one of itsarguments.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
152/607
152CS 538 Spring 2008
First, lets differentiate between(define def1
(let ( (I 0) )(lambda () (set! I (+ I 1)) I)
))
and(define (def2)
(let ( (I 0) )(lambda () (set! I (+ I 1)) I)
))
def1 is a zero argument functionthat increments a local variableand returns its updated value.def2 is a a zero argumentfunction that generatesa functionof zero arguments (thatincrements a local variable and
returns its updated value). Eachcall to def2 creates a differentfunction.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
153/607
153CS 538 Spring 2008
Stack Implemented as aFunction
(define ( stack )(let ( (s () ) )(lambda (op . args) ; var # args(cond
((equal? op 'push!)
(set! s (cons (car args) s))(car s))
((equal? op 'pop!)(if (null? s)
#f(let ( (top (car s)) )
(set! s (cdr s))top )))((equal? op 'empty?)(null? s))(else #f)
))
))
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
154/607
154CS 538 Spring 2008
(define stk (stack));new empty stack
(stk 'push! 1) 1 ;s = (1)
(stk 'push! 3) 3 ;s = (3 1)(stk 'push! 'x) x ;s = (x 3 1)
(stk 'pop!) x ;s = (3 1)
(stk 'empty?) #f ;s = (3 1)
(stk 'dump) #f ;s = (3 1)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
155/607
155CS 538 Spring 2008
Higher-Order Functions
A higher-order function is afunction that takes a function as aparameter or one that returns afunction as its result.
A very important (and useful)higher-order function ismap,which applies a function to a listof values and produces a list orresults:(define (map f L)(if (null? L)
()(cons (f (car L))(map f (cdr L)))
))
Note: In Schemes built-inimplementation ofmap, the orderof function application isunspecified.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
156/607
156CS 538 Spring 2008
(map sqrt '(1 2 3 4 5)) (1 1.414 1.732 2 2.236)
(map (lambda(x) (* x x))'(1 2 3 4 5))
(1 4 9 16 25)
Map may also be used withmultiple argument functions by
supplying more than one list ofarguments:
(map + '(1 2 3) '(4 5 6)) (5 7 9)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
157/607
157CS 538 Spring 2008
The Reduce Function
Another useful higher-orderfunction is reduce, which reducesa list of values to a single value byrepeatedly applying a binaryfunction to the list values.
This function takes a binaryfunction, a list of data values, andan identity value for the binaryfunction:(define(reduce f L id)
(if (null? L)id(f (car L)
(reduce f (cdr L) id))
))
(reduce + '(1 2 3 4 5) 0) 15
(reduce * '(1 2 4 6 8 10) 1) 3840
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
158/607
158CS 538 Spring 2008
(reduce append'((1 2 3) (4 5 6) (7 8)) ())
(1 2 3 4 5 6 7 8)(reduce expt '(2 2 2 2) 1)
= 65536
(reduce expt '(2 2 2 2 2) 1) 265536
(string-length(number->string(reduce expt '(2 2 2 2 2) 1)))
19729 ; digits in 265536
2222
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
159/607
159CS 538 Spring 2008
Sharing vs. Copying
In languages without side-effectsan object can be copied bycopying a pointer (reference) tothe object; a complete new copyof the object isnt needed.
Hence in Scheme (define A B)normally means
A B
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
160/607
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
161/607
161CS 538 Spring 2008
For example,(define A '(1 2))
(define B (cons A A))B = ( (1 2) 1 2)
A B
1
2 ()
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
162/607
162CS 538 Spring 2008
(set-car! (car B) 10)
B = ( (10 2) 10 2)
(define C (cons (copy A) (copy A)))
A B
10
2 ()
C
10
2 ()
10
2 ()
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
163/607
163CS 538 Spring 2008
(set-car! (car C) 20)
C = ((20 2) 10 2)
Similar concerns apply to
strings and vectors, becausetheir internal structure can bechanged.
C
20
2 ()
10
2 ()
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
164/607
164CS 538 Spring 2008
Shallow & Deep Copying
A copy operation that copies apointer (or reference) rather thanthe object itself is a shallow copy.
For example, In Java,Object O1 = new Object();
Object O2 = new Object();O1 = O2; // shallow copy
If the structure within an object isphysically copied, the operation isa deep copy.
In Java, for objects that supportthe clone operation,
O1 = O2.clone(); // deep copy
Even in Javas deep copy (via theclone() operation), objects
referenced from within an objectare shallow copied. Thus given
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
165/607
165CS 538 Spring 2008
class List {
int value;
List next;}
List L,M;
M = L.clone();
L.value andM.value are
independent, but L.next andM.next refer to the same Listobject.
A complete deep copy, that copiesall objects linked directly or
indirectly, is expensive and trickyto implement.
(Consider a complete copy of acircular linked list).
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
166/607
166CS 538 Spring 2008
Equality Checking in Scheme
In Scheme = is used to test fornumeric equality (includingcomparison of different numerictypes). Non-numeric argumentscause a run-time error. Thus
(= 1 1) #t
(= 1 1.0) #t
(= 1 2/2) #t
(= 1 1+0.0i) #t
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
167/607
167CS 538 Spring 2008
To compare non-numeric values,we can use either:
pointer equivalence (do the twooperands point to the sameaddress in memory)
structural equivalence (do the twooperands point to structures with
the same size, shape andcomponents, even if they are indifferent memory locations)
In general pointer equivalence isfaster but less accurate.
Scheme implements both kinds ofequivalence tests.(eqv? obj1 obj2)
This tests ifobj1 and obj2 are
the exact same object. This worksfor atoms and pointers to thesame structure.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
168/607
168CS 538 Spring 2008
(equal? obj1 obj2)
This tests ifobj1 and obj2 are
the same, component bycomponent. This works foratoms, lists, vectors and strings.
(eqv? 1 1) #t
(eqv? 1 (+ 0 1)) #t
(eqv? 1/2 (- 1 1/2)) #t(eqv? (cons 1 2) (cons 1 2))
#f
(eqv? "abc" "abc") #f
(equal? 1 1) #t
(equal? 1 (+ 0 1)) #t
(equal? 1/2 (- 1 1/2)) #t
(equal? (cons 1 2) (cons 1 2)) #t
(equal? "abc" "abc") #t
In general it is wise to use equal?unless speed is a critical factor.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
169/607
169CS 538 Spring 2008
I/O in Scheme
Scheme has simple read and writefunctions, directed tothestandardin and standard out files.(read)
Reads a single Scheme object (anatom, string, vector or list) fromthe standard in file. No quoting isneeded.(write obj)
Writes a single object, obj, to thestandard out file.
(display obj)
Writes obj to the standard out filein a more readable format.(Strings arent quoted, andcharacters arent escaped.)
(newline)Forces a new line on standard outfile.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
170/607
170CS 538 Spring 2008
Ports
Ports are Scheme objects thatinterface with systems files. I/O tofiles is normally done through aport object bound to a systemfile.(open-input-file "path to file")
This returns an input portassociated with the "path tofile" string (which is systemdependent). A run-time error issignalled if"path to file"
specifies an illegal or inaccessiblefile.(read port)
Reads a single Scheme object (anatom, string, vector or list) from
port, which must be an inputport object.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
171/607
171CS 538 Spring 2008
(eof-object? obj)
When the end of an input file is
reached, a special eof-object isreturned. eof-object? testswhether an object is this specialend-of-file marker.(open-output-file "path to file")
This returns an output portassociated with the "path tofile" string (which is systemdependent). A run-time error issignalled if"path to file"specifies an illegal or inaccessible
file.(write obj port)
Writes a single object, obj, to theoutput port specified byport.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
172/607
172CS 538 Spring 2008
(display obj port)
Writes obj to the output port
specified byport. display uses amore readable format than writedoes. (Strings arent quoted, andcharacters arent escaped.)(close-input-port port)
This closes the input portspecified byport.(close-output-port port)
This closes the output portspecified byport.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
173/607
173CS 538 Spring 2008
ExampleReading & Echoing aFile
We will iterate through a file,reading and echoing its contents.We need a good way to doiteration; recursion is neithernatural nor efficient here.
Scheme provides a nicegeneralization of the letexpression that is similar to Csfor loop.(let X ( (id1 val1) (id2 val2) ... )
...(X v1 v2 ...)
)
A name for the let (X in theexample) is provided. As usual,val1 is evaluated and bound toid1,val2 is evaluated and boundto id2, etc. In the body of the let,the let may be called (using its
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
174/607
174CS 538 Spring 2008
name) with a fresh set of valuesfor the let variables. Thus (X v1
v2 ...) starts the next iterationof the let with id1 bound tov1,id2, bound tov2, etc.
The calls look like recursion, butthey are implemented as loopiterations.
For example, in(let loop ( (x 1) (sum 0) )
(if (
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
175/607
175CS 538 Spring 2008
Now a function to read and echo afile is straightforward:
(define (echo filename)(let ((p (open-input-file filename)))
(let loop ( (obj (read p)))
(if (eof-object? obj)
#t ;normal termination
(begin(write obj)
(newline)
(loop (read p))
)
))
)
)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
176/607
176CS 538 Spring 2008
We can create an alternative toecho that uses
(call-with-input-filefilename function)
This function opens filename,creates an input port from it, andthen calls function with thatport as an argument:(define (echo2 filename)(call-with-input-file filename(lambda(port)
(let loop ( (obj (read port)))
(if (eof-object? obj)#t(begin(write obj)
(newline)(loop (read port))
))
))
) )
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
177/607
177CS 538 Spring 2008
Control Flow in Scheme
Normally, Schemes control flow issimple and recursive:
The first argument is evaluated toget a function.
Remaining arguments are
evaluated to get actual parameters. Actual parameters are bound to the
functions formal parameters.
The functions body is evaluated toobtain the value of the function
call.This approach routinely leads todeeply nested expressionevaluation.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
178/607
178CS 538 Spring 2008
As an example, consider a simplefunction that multiplies a list of
integers:(define (*list L)(if (null? L)
1
(* (car L)(*list (cdr L)))
))
The call (*list '(1 2 3 4 5))
expands to(* 1 (* 2 (* 3 (* 4 (* 5 1)))))
But,what if we get clever and decideto improve this function by notingthat if 0 appears anywhere in listL, the product must be 0?
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
179/607
179CS 538 Spring 2008
Lets try(define (*list0 L)
(cond((null? L) 1)
((= 0 (car L)) 0)
(else (* (car L)(*list0 (cdr L))))
)
)This helps a bitwe never gopast a zero in L, but we stillunnecessarily do a sequence ofpending multiplies, all of which
must yield zero!Can we escape from a sequenceof nested calls once we knowtheyre unnecessary?
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
180/607
180CS 538 Spring 2008
Exceptions
In languages like Java, astatement may throwanexception thats caughtby anenclosing exception handler.Code between the statement thatthrows the exception and the
handler that catches it isabandoned.
Lets solve the problem ofavoiding multiplication of zero in
Java, using its exception
mechanism:class Node {
int val;
Node next;
}
class Zero extends Throwable{};
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
181/607
181CS 538 Spring 2008
int mult (Node L) {
try {return multNode(L);
} catch (Zero z) {
return 0;
}
}int multNode(Node L)
throws Zero {
if (L == null)
return 1;
else if (L.val == 0)
throw new Zero();
else returnL.val * multNode(L.next);
}
In this implementation, nomultiplies by zero are ever done.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
182/607
182CS 538 Spring 2008
Continuations
In our Scheme implementation of*list, wed like a way to delaydoing any multiplies until weknow no zeros appear in the list.One approach is to build acontinuationa function that
represents the context in which afunctions return value will beused:(define (*listC L con)
(cond
((null? L) (con 1))((= 0 (car L)) 0)
(else
(*listC (cdr L)
(lambda (n)(* n (con (car L)))))
))
)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
183/607
183CS 538 Spring 2008
The top-level call is(*listC L (lambda (x) x))
For ordinary lists *listC expandsto a series of multiplies, just like*list did.(define (id x) x)
(*listC '(1 2 3) id)
(*listC '(2 3)(lambda (n) (* n (id 1))))
(*listC '(2 3)(lambda (n) (* n 1)))
(*listC '(3)(lambda (n) (* n (* 2 1))))
(*listC '(3)(lambda (n) (* n 2)))
(*listC ()(lambda (n) (* n (* 3 2))))
(*listC () (lambda (n) (* n 6))) (* 1 6) 6
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
184/607
184CS 538 Spring 2008
But for a list with a zero in it, weget a different execution path:
(*listC '(1 0 3) id) (*listC '(0 3)(lambda (n) (* n (id 1)))) 0
No multiplies are done!
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
185/607
185CS 538 Spring 2008
Another Example ofContinuations
Lets redo our list multiplyexample so that if a zero is seenin the list we return a functionthat computes the product of allthe non-zero values and aparameter that is thereplacement value for theunwanted zero value. Thefunction gives the caller a chanceto correct a probable error in the
input data.We create(*list2 L)
Product of all integers in L ifno zero appears
else(lambda (n) (* n product-of-all-nonzeros-in-L)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
186/607
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
187/607
187CS 538 Spring 2008
In the following, we check to seeif*list2 returns a number or a
function. If a function is returned,we call it with 1, effectivelyremoving 0 from the list(let ( (V (*list2 L)) )
(if (number? V)
V(V 1)
)
)
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
188/607
188CS 538 Spring 2008
For ordinary lists *list2 expandsto a series of multiplies, just like
*list did.(*listE '(1 2 3) id)
(*listE '(2 3)(lambda (m) (* m(id 1))))
(*listE '(2 3)(lambda (m) (* m 1)))
(*listE '(3)(lambda (m) (* m(* 2 1))))
(*listE '(3)(lambda (m) (* m 2)))
(*listE ()(lambda (m) (* m(* 3 2))))
(*listE () (lambda (n) (* n 6))) (* 1 6) 6
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
189/607
189CS 538 Spring 2008
But for a list with a zero in it, weget a different execution path:
(*listE '(1 0 3) id) (*listE '(0 3)(lambda (m) (* m(id 1))))
(lambda (n) (* (con n)(* listE '(3) id)))
(lambda (n) (* (* n 1)(* listE '(3) id)))
(lambda (n) (* (* n 1) 3))
This function multiplies n, thereplacement value for 0, by 1 and
3, the non-zero values in the inputlist.
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
190/607
190CS 538 Spring 2008
But note that only one zero valuein the list is handled correctly!
Why?(define (*listE L con)
(cond
((null? L) (con 1))
((= 0 (car L))
(lambda(n)(* (con n)(*listE (cdr L) id))))
(else(*listE (cdr L)(lambda(m)(* m (con (car L))))))
))
8/7/2019 Cs.wisc Fisher Cs538 Lecture All
191/607
191CS 538 Spring 2008
Continuations in Scheme
Scheme provides a built-inmechanism for creatingcontinuations. It has a long name:call-with-current-continuation
This name is often abbreviated as
call/cc(perhaps using define).
call/cc takes a single function asits argument. That function als