It is essential for anyone who wants to be considered a professional in the areas of software to know several languages and several programming paradigms . . . it's not a good idea to know just C++, let alone to know just a single-paradigm language. Much of the inspiration in good programming comes from having learned and appreciated several programming styles.   --Bjarne Stroustrup, C++ author
Chapter 1: P R O G R A M M I N G   L A N G U A G E S   C O N C E P T S
This course covers the concepts of high-level programming languages with a focus is design criteria and evaluation. The best way to learn a language concept is to code in it. Topics covered:

Why learn programming language concepts?

Programming languages are designed to solve problems in a particular programming domain.

l a n g u a g e     e v a l u a t i o n     c r i t e r i a
What makes a language good? Or better than another language?

bubble-sort example

READABILITY
Readability is the ease with which programs can be read and understood given the provisions of the language. Given well-written source how easy is it to understand the meaning of the code? Some languages are easy to write but difficult to read. Regexes (a language albeit not a programming language) demonstrate this problem:
 
^.*[0-9a-z]+?\([a-zA-Z}*$\)    # difficult to proofread and debug
Lisp is equally easy to write but difficult to read (from H2wUc):

(lambda (*<8-]= *<8-[= ) (or *<8-]= *<8-[= ))

(defun :-] (<) (= < 2))

(defun !(!)(if(and(funcall(lambda(!)(if(and '(< 0)(< ! 2))1 nil))(1+ !))
(not(null '(lambda(!)(if(< 1 !)t nil)))))1(* !(!(1- !))))) 
WRITABILITY
Writability is a measure of coding efficiency. It is the ease at which a coder can learn the language in order to write code and how long it takes to write code once you know the language.

RELIABILITY
Reliability is conformance to specification under all circumstances without fault.
COST
Total cost of a language throughout entire language lifecycle from development, testing and maintenance.
OTHER CRITERIA

Prescelt's Comparison Study

l a n g u a g e     d e s i g n
Influences on Language Design Evolution of Language Design
Language Classifications
Programming languages are sometimes categorized into "generations": Languages are more importantly classified into one of several primary design paradigms: Language Design Trade-Offs

i m p l e m e n t a t i o n
Three Methods Preprocessors Compilation and Execution Phases Pure Interpretation Hybrid Implementation Systems Development Environments
t e r m i n o l o g y
Programming methodology
defines the overall approach a programmer takes to write software in a programming language. Programming methodology is the theoretical model that underlies language design. New methodologies (e.g., object-oriented) result in new language designs.
Von Neumann architecture
the prevalent design of modern computer systems. In this design data and programs are stored in memory, memory is separate from the CPU, instructions and data are piped from memory to the CPU. Execution of machine code on a von Neumann architecture follows this fetch-execute cycle:
      initialize program counter (PC) with address of first instruction
      repeat forever
         fetch the instruction in PC 
         increment PC 
         decode instruction
         execute instruction
      end repeat 
Von Neumann bottleneck
this is the primary limiting factor in the speed of computers today (not processor speed). The bottleneck occurs because the connection speed between memory and the processor is slower than the speed at which instructions can be executed by the CPU. Parallelism and the use of cache attempt to solve this problem.
side effect
is any modification to the state of a running program. Side effects may be intentional (imperative languages depend on side effects in the form of mutable data and changes to input and output)or unintentional (generally a fault). A purely functional language has no side effects. Functional programs will behave the same in any context and can be executed in parallel without interference. Such programs are easily verified and optimized. This is a big advantage and may outweight the limitations of a functional language for some applications.
pointer
a reference (address) to a memory location. In C a pointer is a primitive data type that stores a memory address. (see code)
     int * stuff;
     int num = 5;
     stuff = #
     printf(%p %d,stuff, *stuff);
     stuff++; // what does this do?
     stuff = stuff/2;   // pointer division is not legal  
alias
is two or more references to the same memory location. Pointers can be used as aliases in C/C++, which most consider to be the language's biggest liability. Aliasing can violate both reliability and readability. Assume you have a class Student that uses dynamic memory allocation for the student's name:
   char * name; 
If an overload assignment operator is not coded, these statements will produce cross-linked pointers:
   Student a("Sam Spade");
  Student b("Joe Smoo")
  a = b;  // two pointers are now pointing to the same memory location 
oorthogonality
is non-interference; e.g., orthogonal vectors. Orthogonality in a computer instruction set means that all instructions can be uniquely combined with all registers and addressing modes. In high-level languages, orthogonality means that language primitives can be consistently combined without exception. Non-orthogonality makes a language harder to learn. Complete orthogonality is impossible to achieve unless the language is so simple to be useless. Orthogonality requires a small set of primitives--the larger the set, the more difficult it is to maintain orthogonality.

For example, the primitive constructs in C/C++ include arithmetic operators (+ , -, * , /) and scalar data types int, float, double, pointer. In a completely orthogonal language it should be feasible to combine all operators with all data types.

C/C++ is not orthogonal because arithmetic operators do not consistently work on pointers.

  int  a = 5 ;
  int  b = 10;
  int  c = 15 ;

  int * aptr = & a;
  int * bptr = & b;
  int * cptr = & c;

  a++; // legal but does not behave like increment on integers 
  a = b * c;  // OK
  aptr = bptr;  // OK
  aptr = bptr + cptr;  // illegal
  aptr = bptr * cptr;  // illegal
C++ overloaded << and >> operators are non-orthogonal: they can mean bit shifting or output/input depending on the context (Stroustroup what were you thinking). Other examples of non-orthogonality in C:

1. C has two built-in data structures, arrays and records (structs). Structs can be returned from functions but arrays cannot.
2. A member of a struct can have any type except void or a structure of the same type.
3. An array element can be any data type except void or a function.
4. Parameters are passed by value, unless they are arrays, in which case they are passed by reference.

scalar
data type is one that cannot be divided into other data types. Examples of scalars are int, char, double, char *. Scalars are addressed by a single memory address. Examples of non-scalars are arrays, classes, and records. Non-scalars are addressable by more than one memory address. In the beginning, all data were scalars - arrays were added next.
top
Chapter 14.1 - 14.4: E X C E P T I O N   H A N D L I N G
C++ sample code
C++ exception handling FAQ
C++ Exception Classes
Exception handling drawbacks

The concepts in this chapter will be investigated hands-on in this week's lab.

Basic Concepts
An exception is an asynchronous event of some kind, generally an error. Without exception handling, when an exception occurs, control is passed to the kernel and the program terminates. With exception handling the programmer can trap the exception and gracefully terminate of continue. Processing the exception is called *exception handling* Many languages allow programs to trap input/output errors (including EOF).

Most common exceptions: divide by zero, illegal memory access (dereferencing a bad pointer, array out-of-bounds), file open errors, input errors (reading float into char), reading past EOF

An exception is *raised* when its associated event occurs. The exception handling code unit is called an *exception handler*.

User-defined Exception Handling
A language that does not have exception handling built-in can still define, detect, raise, and handle exceptions Pass an argument (flag or error msg) to an error-handling routing or return a flag (boolean, int) Have some mechanism for interpreting what the return flag means (see Unix strcmp) Give exception handling utilities global scope
Advantages of Built-in Exception Handling in C++
Added to C++ in 1990 (Design based on CLU, Ada, and ML) Code reusability, uniformity, promotes readability Error detection code is tedious to write and clutters the program Allows you to rethrow back to main, unwind the runtime stack and perform cleanup (very difficult to code otherwise) Saves the return value for something other than error handling Supports dynamic memory management if objects are allocated in a try block since destructors are called upon exiting the block Increases chances that a program can recover without a complete crash
Things you should know about exception handling in any language
Exception Handling in C++
Basic syntax:

  try {
    throw  
  }
  catch (formal parameter) {
     throw    // optional re-throw will propogate through runtime state
  }
  catch (...) { // a generic handler
  }
Specific example:

  const int DivideByZero = 10;
  //....
  double divide(double x, double y) {
      if(y==0) throw DivideByZero;
      return x/y;
  }
  ///...
  try {
     divide(10, 0);
  }
  catch(int i) {
    if (i==DivideByZero) cerr << "Divide by zero error";
  }
// example of error objects

  class DivideByZero
  {
      public:
          double divisor;
          DivideByZero(double x);
  };
  DivideByZero::DivideByZero(double x) : divisor(x)
  {}
  int divide(int x, int y)
  {
      if(y==0)
      {
          throw DivideByZero(x);
      }
  }
  try
  {
      divide(12, 0);
  }
  catch (DivideByZero divZero)
  {
      cerr<<"Attempted to divide "<<divZero.divisor<<" by zero";
  }
Notes on C++ facility: top