CS374: Programming Language Principles - Programming Paradigms
Activity Goals
The goals of this activity are:- To define the imperative, declarative (functional and logic), object-oriented, and scripting programming paradigms
- To explore concurrency within programming paradigms
Supplemental Reading
Feel free to visit these resources for supplemental background reading material.- Concise Introduction to Prolog
- The Scheme Programming Language
- Bash Syntax Reference
- Bash Scripting Tutorial
- MapReduce
- Closures in Scheme
The Activity
Directions
Consider the activity models and answer the questions provided. First reflect on these questions on your own briefly, before discussing and comparing your thoughts with your group. Appoint one member of your group to discuss your findings with the class, and the rest of the group should help that member prepare their response. Answer each question individually from the activity on the Class Activity Questions discussion board. After class, think about the questions in the reflective prompt and respond to those individually in your notebook. Report out on areas of disagreement or items for which you and your group identified alternative approaches. Write down and report out questions you encountered along the way for group discussion.Model 1: Imperative Languages
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class Main { public static void main(String[] args) { int a = 1 , b = 2 , c = 1 ; float discriminant = Math.sqrt( 4.0 *a*c) / 2 *a; float root = -b + discriminant; System.out.println(root); root = -b - discriminant; System.out.println(root); } } |
Questions
- What defines a statement?
- What, in general, does a statement realy do?
- At what points do the value of root change?
- What would happen if
a
is 0? - How can we represent this program using an Object-Oriented style? What state might the object represent?
Model 2: The C Programming Language and Memory Management
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include <string.h> #include <stdlib.h> #include <stdio.h> struct Person { char * name; int age; float salary; }; void tax( struct Person* p) { if (p->salary > 100000) { p->salary = p->salary * 0.85; } else { p->salary = p->salary * 0.95; } } int main( void ) { struct Person* bill = ( struct Person*) malloc ( sizeof ( struct Person)); bill->name = ( char *) malloc ( strlen ( "Bill" )+1); strncpy (bill->name, "Bill" , strlen ( "Bill" )+1); bill->age = 38; bill->salary = 20000; tax(bill); printf ( "%s (%d): %f\n" , bill->name, bill->age, bill->salary); free (bill); } |
Questions
- What is the value of
bill->salary
after the call totax()
? - The above program has a memory leak. Which variable should also be freed?
- Why is there a
+1
in themalloc
call onbill->name
? - Suppose we had set
p
equal to a newlymalloc
'ed person intax
. How would this affectbill
?
Model 3: The Object-Oriented Paradigm
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | import java.util.Random; public abstract class Vehicle { protected int gear; protected boolean parked; protected int speed; protected boolean locked; public Vehicle() { this .gear = 1 ; this .parked = true ; this .speed = 0 ; this .locked = true ; } public void drive( int speed) { if ( this .parked == true ) { this .parked = false ; } this .speed = speed; } // return a boolean if the vehicle is parked public abstract boolean stop(); public int getSpeed() { return this .speed; } public void unlock() { this .locked = false ; } public void lock() { this .locked = true ; } } public interface Home { public int cook(); public void makeBed(); } public class Car extends Vehicle { public Car() { super (); } public void drive( int speed) { super .drive(speed); this .gear = this .speed / 10 ; } // return a boolean if the vehicle is parked public boolean stop() { this .speed = 0 ; this .gear = 1 ; return this .parked; } } // Unlike interfaces, you can only extend a single class public class MotorHome extends Vehicle implements Home { private boolean bedmade; public MotorHome() { super (); this .bedmade = true ; } public void drive( int speed) { super .drive(speed); this .gear = this .speed / 5 ; } // return a boolean if the vehicle is parked public boolean stop() { this .speed = 0 ; this .gear = 1 ; return this .parked; } public int cook() { return 1 ; // yum? } public void makeBed() { this .bedmade = true ; } public boolean isBedMade() { return this .bedmade; } } class Main { public static void main(String[] args) { Random r = new Random(); Vehicle[] vehicles = new Vehicle[ 2 ]; Car c = new Car(); MotorHome m = new MotorHome(); vehicles[ 0 ] = c; vehicles[ 1 ] = m; m.makeBed(); for (Vehicle v: vehicles) { v.drive(r.nextInt( 50 )); } // Methods in the Interface can be called on variables whose type is just the interface, no matter what it really is! System.out.println( "How fast is the car driving? " + vehicles[ 0 ].getSpeed()); System.out.println( "How about the Motor Home? " + vehicles[ 1 ].getSpeed()); // Methods specific to a class can always be called from the object. System.out.println( "Is the Motor Home bed made? " + m.isBedMade()); } } |
Questions
- How did each file change above by converting the
Vehicle
interface to a class? - By converting the
Vehicle
interface to a class, what can we now define in aVehicle
that we could not define in theinterface
? - You can implement an
interface
; what is the keyword to subclass a class? - From context, what do you think the abstract keyword means in the
Vehicle
class? - From context, what do you think the call to
super()
does? - Notice that some elements are scoped to be
public
andprivate
, like before, but now some items areprotected
. Which items areprotected
, and in which files do they reside? What do you think this scope allows/disallows? - Sketch out an object-oriented design representing students and courses, in which students are enrolled in one or more sections of the course.
Model 4: Imperative Languages
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <math.h> #include <stdio.h> void calcroot( float * root, float discriminant, int b) { *root = -b + discriminant; } int main( void ) { int a = 1, b = 2, c = 1; float discriminant = sqrt (4.0*a*c) / 2*a; float root = 0; calcroot(&root, discriminant, b); printf ( "%d\n" , root); calcroot(&root, -discriminant, b); printf ( "%d\n" , root); } |
Questions
- At what points do the value of
root
change? Where are they changed, and where are they effective? - What would happen if
a
is 0? - How many copies of
discriminant
exist on the call tocalcroot
? - How does the
calcroot
function know to use thediscriminant
variable in its local function? - What would happen if
discriminant
was modified insidecalcroot
? Why is this different than for theroot
variable?
Model 5: Declarative Languages - Functional
1 2 3 4 5 6 7 8 9 | ( define L ( list 'a 'b 'c )) ( car L) ( cdr L) ( define x ( + 3 2 )) ( + x 5 ) ( define add + ) (add 3 2 ) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | ( define square ( lambda (n) ( * n n) ) ) ( define pow ( lambda (n k) ( if ( = k 0 ) 1 ( * n (pow n ( - k 1 ))) ) ) ) (square (pow 5 3 )) |
Questions
- What is a statement in Scheme?
- What shared variables exist in this program?
- What are some potential advantages of Functional Programming as a paradigm?
Model 6: The Scheme Programming Language
1 2 3 4 5 | ( define y ( lambda (m x b) ( + ( * x m) b))) (y 5 6 7 ) |
1 2 3 4 5 6 7 8 9 10 11 | ( define v0 3 ) ( define t 5 ) ( define a 9.80665 ) ( define square ( lambda (n) ( * n n))) ( + ( * v0 t) ( * 0.5 ( * a ( * t t)))) ( + ( * v0 t) ( * 0.5 ( * a (square t)))) |
1 2 3 4 5 6 7 8 | ( define czr ( lambda (l) ( if ( null? ( cdr l)) ( car l) (czr ( cdr l)) ) ) ) |
1 2 3 4 5 6 7 8 9 10 | ( define plusminus ( lambda (a b) ( ( lambda (x y) ( list ( + x y) ( - x y))) a b ) ) ) (plusminus 6 2 ) |
1 2 3 4 | ( define L1 '( 1 2 3 )) ( define L2 '( 4 5 6 )) ( define L3 ( map - L1 L2)) ( apply + L3) |
Questions
- How are function parameters handled in Scheme? Are they passed by value or by reference?
- What is a function in Scheme? How is it represented?
- What does
czr
do in your own words? - Write a function to count the number of items in a list using a recursive call and a base case, using
czr
as a guide to traversing a list. - Diagram the binding of the values in the call to
plusminus
to the anonymous lambda function. - What is the result of the
map
/apply
sequence? What would happen ifmap
were applied to only a single list?
Model 7: Declarative Languages - Logic
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | course( CS173 ). course( CS374 ). course( CS374 ). course( CS475 ). prereq( CS174 , CS173 ). prereq( CS374 , CS174 ). ?-prereq( CS475 , CS374 ). % no /* Horn Clause: does there exist a Z such that Y is a prereq of Z AND that X must be taken before Z? */ take_before( X , Y ) :- prereq( Z , Y ), take_before( X , Z ). % Transitive closure through recursion ?-take_before( CS173 , CS374 ). % yes |
Questions
- What query would result in a
yes
response according to the prerequisite rules above? - In your own words, what does the
take_before
clause specify, and how does it do so? - Write a Horn Clause that specifies that one might go outside if it is warm and not raining outside.
Model 8: Declarative Languages - Prolog
1 2 3 4 5 | perfect( N ) :- between (1, inf , N ), U is N // 2, findall ( D , ( between (1, U , D ), N mod D =:= 0), Ds ), sumlist ( Ds , N ). |
Questions
- Describe, in your own words, what this program does.
Model 9: Applications of the Declarative Paradigm - Pythonic List Comprehension
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | heights = [ 50 , 62 , 73 , 58 , 46 , 49 , 43 ] minheight = 48 canride = [] # version 1 for height in heights: if height > minheight: canride.append(height) # version 2 canride2 = [height for height in heights if height > minheight] # version 3 canridebool = list ( map ( lambda height: height > minheight, heights)) canride3 = [x[ 0 ] for x in zip (heights, canridebool) if x[ 1 ]] |
Questions
- What are the advantages and disadvantages of each approach?
- Which version do you find more convenient and why?
Model 10: Scripting Languages - Bash
1 2 3 4 5 6 7 | #!/bin/bash COURSE=CS374 cd ${COURSE} FILES=$( ls *.txt) echo ${FILES} |
Questions
- What is a statement in this language?
- How are variables expanded?
- What potential benefit can you see with the use of shell scripting?
- Are scripting languages imperative or declarative?
Model 11: Programming Constructs in bash
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/bin/bash let "x = $1 * 2" # equivalent to x=$(expr $1 \* 2) and x=$(($1 * 2)) let x++ NAME= "Alexandra" echo ${NAME} has ${ #NAME} characters in it echo ${NAME} goes by ${NAME:0:4} for short. echo ${NAME%a*} ${NAME%%a*} # the # sign instead of % in the variable expansion # does this behavior from the left instead of the right echo ${NAME /xandra/jandro } echo Here is a name that doesn't exist yet: ${NAME2} echo Here is the value of another variable: ${NAME2:=Unknown} echo How about now: ${NAME2} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #!/bin/bash x=0 while [[ ${x} -lt 10 ]] # (( ${x} < 10 )) is also acceptable do echo ${x} x=$((${x} + 1)) done if [[ ${x} - eq 10 ]] # (( ${x} == 10 )) is also acceptable then echo "x is now 10" else echo "x is not 10 but rather ${x}" fi if [[ -e 'doit.sh' ]] then echo "doit.sh exists" else echo "doit.sh does not exist" fi if [[ -d 'doit.sh' ]] then echo "doit.sh is a directory" else echo "doit.sh is not a directory" fi |
Questions
- What do you think
$1
means? - If
$1
is 5, what is the final value ofx
? - Why was the
\
character necessary in thex=$(expr $1 \* 2)
command? - What do each of the variable expansions do in the first example above?
- What would happen if the
-lt
in the loop above was modified to<
? Similarly, what is the difference between-eq
and=
in bash?
Model 12: Concurrent and Socket Programming in the Go Language
Concurrency in the Go Language
Non-Blocking Concurrency Channels in the Go Language
Questions
- How might you add concurrency to a socket program to allow the program to send data without having to wait to receive a message?