This review session assumes that the final covers the material starting from
the Python lectures.

The exam will be multiple choice/multiple answer/code reading/fill in the blank/short answer
with a Python programming question


Python
    Goal of scripting languages
        --Accomplish specific tasks quickly without concern for machine efficiency
        --Emphasis is on programmer efficiency

    Characteristics of scripting languages
        Economy of expression
	Lack of variable declarations
	Flexible dynamic typing
	Easy access to system facilities
	Sophisticated pattern-matching and string manipulation
	Built-in high-level data types
	    lists
	    hash tables (associative arrays)
	Interpreted
        Prototype-instance models rather than class-instance models

    Syntax you must memorize: This list is exhaustive for the features but
        not for all the syntax for these features. See the appropriate parts
	of the Python notes for all the syntax

	Values: Numbers, strings, boolean values, None

	Arithmetic, relational, and boolean operators
	
        Control structures: functions, conditionals, loops
	    for...in and while
	        else: on loops
		use range() fct to do counting loops
	    def fct(...):
	    if/elif/else
	Lists:
	    use array slices when appropriate
	    .pop: remove a value from the back of a list
	    .insert(0, val): insert val at beginning of the list
	    .append
	    .popleft: remove a value from the front of a list
	Dictionaries
	Tuples
	Iteration over sequences
            dict.keys(): returns list of keys
	    dict.iteritems(): returns list of key/value pairs
	    enumerate(list): returns index/value pairs
	    for v1, v2 in zip(list1, list2): Allows you to loop over two or
	        more sequences at the same time--pairs corresponding entries
		from each sequence.
	Sorting
	    use either list.sort or sorted(list)
	    sorted([5, 2, 3, 1, 4], reverse=True): sorts in reverse
	    sorting using lambda functions
	        tuples: sorted(student_tuples, key=lambda student: student[2])
		objects: sorted(student_objects, key=lambda student: student.age)
	    primary and secondary sorting: return tuple of values
	        sorted(student_objects, key=lambda student: (student.age, student.name))
            attribute accessor functions: simplify accesses to attributes
	        imported from operator module
		itemgetter(index): returns element at index position in a tuple
		attrgetter(attribute): returns value of attribute in an object

	Functional Operations on Lists
	    filter
	    map
	    reduce

	I/O

	    opening/closing files
	    reading from a file/stdin
	    writing formatted output to stdout/file
	    .split: splits a string into fields
	    .strip: strips leading and trailing spaces
	    for x in file: files can be read like lines in a list

        Other things to know for multiple choice/multiple answer

	1) Parameters in functions: how declared, how passed, etc
	2) Generator functions: yield statement
	3) Modules
	   a) how to create modules
	   b) how to import modules
	   c) how to create packages using __init__.py
	4) Exception handling
	   a) basic try/except/else/finally syntax
	   b) how to raise an exception
	   c) how to create user exceptions
	5) Classes
	   a) use prototype-instance model rather than class-instance model
	       i) all prototypes are objects
	       ii) can dynamically add/delete instance variables from any
	       	   object, including methods
	   b) know difference between a function in a prototype and a method
	      in an instance
	   c) One constructor per prototype and its name is __init__
	   d) First argument to methods is a pointer to self
	   e) Know how to create objects and call methods
	   f) Know why it's important to create instance variables in
	      constructor rather than in the prototype--problem with
	      variables that store mutable types

Concurrency
    Know definitions: Concurrency, process, thread, deadlock, starvation, livelock

    Java's Thread mechanism
    	Runnable Interface
	Thread Class
    Handling Interrupts
    	Interrupted Exception thrown by some methods (e.g., sleep())
	Thread.interrupted() can be used to check if thread is interrupted
		if exception doesn't exist
    Synchronization
        Why we need it--race conditions
	   Thread interference
	   Memory inconsistency: thread A depends on thread B to perform a
	      write before it performs read (happens-before relationship)
    Synchronization to avoid Thread Interference--typically need to keep
        synchronized objects that are shared among threads (e.g., the
	timekeeper and random number generator objects in the race problem)
        Synchronized Methods
	Synchronized Statements: help avoid starvation
    Synchronization to Enforce happens-before relationships (i.e., avoid
    		    memory inconsistency)
        .join(): forces a thread to completely finish
	.wait(): relinquishes a lock and waits on another process to perform
		 some action before resuming
	    .notify(), .notifyall(): indicates that you're about to release
	        a lock--generally return after doing this, which releases
		the lock. You can also call wait() after this to release
		the lock
	    .wait() is often called from within a synchronized method
	Volatile Methods: Do not explicitly prevent thread interference but
		 do force threads to write values to memory rather than
		 holding them in registers

    Sockets
        What are sockets
	How to write a client/server interaction in Java
	    Server listens using SocketServer class
	        When it accepts a connection it gets a Socket and can
		   communicate with the client via the Socket's input and
		   output streams
		Frequently forks a client thread if it's dealing with
		   multiple clients
	    Client gets a Socket instance when the server accepts a
	        connection
		Can communicate with server via Socket's input and output
		   streams
		If client must also listen to stdin, then it forks a
		   separate thread so it can monitor stdin on one thread
		   and server input on the other thread
	    Typically the server maintains one or more synchronized data
	        objects that helps it keep info on the clients
	Detecting shutdown
	    Can't use .close()
	    shutdown has occurred when the Socket's input stream returns
	    	     a null line

    High level Concurrency Mechanisms in Java
        Mutex Locks
	    Lock is the interface that specifies the Mutex Lock API
	    Advantage over old-style Java locks: Can try to acquire a lock
	    	but back out if lock can't be acquired--helps avoid deadlock
	    ReentrantLock is the class that typically implements a mutex
	        lock
		--a thread that holds the lock can execute any method that
		  attempts to acquire the lock

    	Thread Pools
	    Task: computation you want repeated one or more times--handed
	       to a thread pool
	    Thread pool: Pool of one or more threads to which a task may
	    	   be assigned
	       Java manages the threads and assigns them to cores
	       Executors manage the thread pool
	           Executor
		   ExecutorService: provides control over tasks
		       Allows you to terminate a task
		       Allows you to retrieve a value from a task
		       Allows you to shut down the pool
		       Provides Fork/Join pools so work can be recursively
		          decomposed into subtasks for parallelism
		   ScheduledExecutorService: allows scheduling of tasks
		       Supports future execution of a task
		       Supports periodic execution of a task

         Concurrent Collections
	     Unsynchronized collections fail "fast" if concurrent execution
	        is attempted but only guarantee "best effort"
	     Synchronized classes
	         BlockingQueue: Fifo queue for producer/consumer
		 ConcurrentMap: Hash table
		 ConcurrentNavigableMap: Sorted map
		 Vector
	     Why not to use synchronized class for single-threaded apps
	         Overhead of obtaining/releasing locks
		 Must dump registers to memory when methods complete thus
		    disrupting pipelined processors

	  ThreadLocalRandom: A random number generator isolated to the current
	     thread
	     --Avoids sharing/contention with Math.random()
	     --Faster than generating your own random number objects

	  Atomic Variables: Increment variables that need to perform simple
	     atomic operations such as counting or setting and retrieving
	     a value

Functional Programming

    Derived from Church's lambda calculus
        emphasizes computing by composing functions and using parameters to
	communicate state information between functions

    Conceptual features
        Defines outputs of a program as a mathematical function
	No side effects
	Emphasizes recursion rather than iteration

    Characteristics that differentiate it from imperative languages
        1st class functions
	higher order functions
	implicit polymorphism
	built-in lists
	structured function returns
	constructors for aggregates
	garbage collection

    Improving efficiency of functional programs: use tail recursion
        tail recursion: function in which additional computation never
	   follows a recursive call.
	compiler can replace recursion with iteration and re-using the
	   stack frame
	can re-write a non-tail recursive function into a tail recursive
	   function using continuations
	   continuation "continues" a computation by making modifications
	      to the arguments in the next recursive call: so it holds
	      results of computations in the arguments

    Program construction methods
        Inductive construction: Follows natural recursive definition
	   akin to post-processing a list
	Tail recursion
	   uses continuation arguments
	   akin to pre-processing a list

   	   Example factorial

	   Inductive construction

	   (define fact (lambda (n)
	     (cond
	       ((= n 0) 1)
	       ((= n 1) 1)
	       (#t (* n (fact (-n 1)))))))

	   Tail recursive construction
	   
	    (define fact (lambda (n)
	        (letrec ((factHelper (lambda (n productThusFar)
	           (cond
		    ((= n 0) productThusFar)
		    ((= n 1) productThusFar)
		    (#t (factHelper (- n 1) (* n productThusFar)))))))
	          (factHelper n 1))))

      Scheme: Go over the scheme notes and make sure you know how to read
          Scheme code--you won't have to write a scheme program but you may
	  have to execute a scheme function and tell me what it outputs

      Evaluation Order
          Applicative Evaluation
	  Normal Form Evaluation
	  Scheme uses applicative evaluation for functions and normal form
	     evaluation for special "forms" such as if, cond, boolean operators
	  Memoization to speed up normal form evaluation
	  Strict vs non-strict languages
	      strict: all arguments must be well-defined so applicative
	         evaluation can be used
	      non-strict: not all arguments must be well-defined so normal
	         form evaluation must be used
	  Scheme: can use delay and force to obtain generator functions


      Higher Order Functions
          The Big 4
	      Filter
	      Map: breaks a computation into a computation over identical
	      	   subtasks
	      Reduce: summarizes a computation by combining the results of
	      	      subtasks or a list
	      Currying: makes an argument to a function constant--used for
	          syntactic sugar

    Advantages of functional languages
        lack of side effects makes programs easier to understand
	lack of explicit evaluation order (in some languages) offers
	    possibility of parallel evaluation (e.g. MultiLisp)
	lack of side effects and explicit evaluation order simplifies
	         some things for a compiler (provided you don't blow it in
		 other ways)
	programs are often surprisingly short
        language can be extremely small and yet powerful

     Problems with functional languages
        Performance
	    trivial update problem
	        initialization of complex structures
		summarization problem
		in-place mutation
	    heavy use of pointers (locality problem)
	    frequent procedure calls
	    heavy space use for recursion
	    requires garbage collection
	requires a different mode of thinking by the programmer
	difficult to integrate I/O into purely functional model