CS374: Programming Language Principles - Code Structure
Activity Goals
The goals of this activity are:- To explain the programming language constructs of expressions
- To explain the programming language constructs of conditionals
- To explain the programming language constructs of functions
- To explain the programming language constructs of exceptions
- To relate complex data structures to their position in memory and pointer- or reference-based representation in memory
Supplemental Reading
Feel free to visit these resources for supplemental background reading material.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: Assignment Expressions
1 2 3 4 5 6 7 8 9 | int x = 5; x = x + 1; if (x == 6) { x = printf ( "%d\n" , x); // is this legal? } // x + 1 = x; |
Questions
- In what contexts do you see
x
being used in this program? How about the equals sign? - Why is there a
=
in some instances but a==
in others? What would happen if thex == 6
were replaced withx = 6
? How does this compare to other languages? - Which
x
variable uses would be referred to as l-vals, and which as r-vals?
Model 2: l-val and r-val Semantics
1 2 3 4 5 6 7 8 9 | int [] heights = {48, 42, 65, 58}; int & height( int i) { return heights[i]; } int main() { height(1) = 44; // person 1 grew! Is this legal? } |
Questions
- In what contexts is heights an l-val, and in which is it an r-val?
- What does the ampersand mean in this program?
Model 3: Conditionals
1 2 3 4 5 6 7 8 9 | int main() { int x = 5; if (x < 10) { x = x + 1; } else { x = x - 1; } } |
Questions
- Rewrite this code using only
GOTO
statements for the body of theif
andelse
clauses, like in BASIC. - Which structure do you prefer and why?
Model 4: Iteration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class Driver { public static void main(String[] args) { ArrayList<String> people = new ArrayList<String>(); // populate with Strings... Iterator i = people.iterator(); while (i.hasNext()) { String person = i.next(); System.out.println(person); } } } |
Questions
- Re-write this loop with a traditional counter loop. How might this work using
GOTO
structures?
Model 5: Functions and Evaluation Strategies
1 2 3 4 5 6 7 8 9 10 | int main() { // suppose this returns some pointer that might be NULL // and that ListNode is a traditional linked list node struct ListNode* ptr = getHead(); // Suppose getNext(ListNode* x) returns x->next if (ptr != NULL && getNext(ptr) == NULL) { printf ( "I am the only elment in this list!\n" ); } } |
Questions
- In C, what would happen if
ptr
isNULL
? Would this program fail? - From context, what do you think lazy evaluation means?
- Would this outcome be different in an eager evaluation language?
Model 6: Generator Functions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # explicitly write a generator function def double (L): for x in L: yield x*2 # eggs will be a generator eggs = double ([1, 2, 3, 4, 5]) # the above is equivalent to ("generator comprehension"?) eggs = (x*2 for x in [1, 2, 3, 4, 5]) # need to do this if you need a list eggs = list( double ([1, 2, 3, 4, 5])) # the above is equivalent to (list comprehension) eggs = [x*2 for x in [1, 2, 3, 4, 5]] |
Questions
- What, in your own words, does a generator do?
Model 7: Recursive Functions
1 2 3 4 5 6 7 8 9 10 | ; https: //www.cs.trinity.edu/~jhowland/ccsc98/ccsc98/node5.html ; scheme < fact.scm (define factorial (lambda(n) ( if (= n 0) 1 (* n (factorial (- n 1)))))) (factorial 5) |
Questions
- What do you think is meant by tail recursion?
- Define a recursive approach to find the last item in a list in Scheme. Note that
(if (null? (cdr l))
asks if thecdr
of listl
isnull
. - Is each call to
factorial
distinct? In other words, what is each value ofn
in each function call? Based on this, what do you think is the difference between pass-by-reference and pass-by-value in a function call?
Model 8: Lazy and Eager Evaluation
1 2 3 4 5 6 | (define (fibonacci n) ( if (<= n 2) 1 (+ (fibonacci (- n 1)) (fibonacci (- n 2))) ) ) |
Questions
- How many times is
fibonacci(2)
called if the initial call was tofibonacci(3)
? - How many times does
fibonacci(2)
really need to be called? What could we do to help ensure that this happens?
Model 9: Old Fashioned Exceptions
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <stdio.h> #include <stdlib.h> int main() { int * x = ( int *) malloc (10000000000000* sizeof ( int )); if (x == NULL) { perror ( "malloc" ); printf ( "%d\n" , errno ); } // printf("%d\n", 5 / 0); // what would happen? } |
Questions
- What is the value of
x
ifmalloc
fails? - What do you think
perror
does? - What is
errno
? - What would happen if a second syscall fails before checking the value of
errno
? Based on this, what can you say about the variableerrno
? - In what ways can the
read
syscall fail? - What would happen if you divided by 0 in C?
Model 10: Explicit Exception Handling
1 2 3 4 5 6 7 8 | try : foo() catch SomeError: print( "SomeError occurred" ) catch SomeOtherError: print( "SomeOtherError occurred" ) catch : print( "Any other type of error occurred" ) |
Questions
- How might you use this structure to recover and proceed when an exception occurs?
- What might you do if you encounter an exception from which you cannot recover?
Model 11: Throwing Exceptions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class Driver { public double doSomething( int x) throws Exception { if (x == 0) { throw new Exception( "Can't divide by 0!" ); } return 10.0 / x; } public static void main(String[] args) { try { System.out.println(doSomething(0)); catch (Exception e) { Sytstem.out.println(e.getMessage()); e.printStackTrace(); } } } |
Questions
- How can this approach be used to enforce preconditions?
Model 12: Garbage Collection
1 2 3 4 5 6 7 8 9 10 11 | public class Driver { public double doSomething( int x) { ArrayList<String> x = new ArrayList<String>(); // work with x } public static void main(String[] args) { doSomething(); } } |
Questions
- When is
x
discarded? - How does this differ from C++?
- What are some strategies for determining when it is safe to garbage collect a variable?