680 likes | 1.28k Views
COSC3306: Programming Paradigms Lecture 1: Introduction. Haibin Zhu, Ph.D. Computer Science Nipissing University (C) 2003. Course Outline. This course will give you the opportunity to learn the fundamental concepts underlying modern programming languages.
E N D
COSC3306:Programming ParadigmsLecture 1: Introduction Haibin Zhu, Ph.D. Computer Science Nipissing University (C) 2003
Course Outline • This course will give you the opportunity to learn the fundamental concepts underlying modern programming languages. • The primary focus is on understanding concepts, however, as a practical consequence, you will write several small programs in different languages. • We will study a small set of representative programming languages and use them to develop an understanding of how different programming language concepts are implemented by a language designer, and their impact on the programmer.
Textbook • Textbook: Seyed H. Roosta, Foundations of Programming Languages: Design and Implementation, Thomson, Brook/Cole, 2003. ISBN: 0-534-39303-9 • Reference: • Robert Sebesta, Concepts of Programming Languages, 5th Edition, Addison-Wesley, 2001. • Other books about special languages
The principal paradigms • Imperative Programming (C) • Object-Oriented Programming (C++) • Logic/Declarative Programming (Prolog) • Functional/Applicative Programming (Lisp)
Languages we will learn • C for efficient imperative programming with static types. • C++ for object-oriented programming with static types and ad hoc, subtype and parametric polymorphism. • Lisp for applicative programming. • Prolog for Logical programming.
Introduction • Programming Languages • Programming Language Design • Programming Language Processing
Programming Languages • A set of statements/commands used to direct a computer to do something useful. • A notational system for describing computations in both machine readable and human readable form. • A programming language is a language intended for the description of programs.
Why So Many Programming Paradigms and Languages? • Building automated software tools that help people cope effectively with complexity. • Failure to manage complexity can result in catastrophic errors. A small coding mistake can kill somebody! • Looking for better ways to build software tools to deal with various computationally solvable problems. • There have been literally hundreds of different programming languages designed, some general purpose, others special purpose. Many are now obsolete.
Complexity • The sheer number of logic components in a modern CPU requires thousands of simulations to check for problems, but that doesn’t mean they are all found (remember the Pentium FDIV bug?). • A system to predict tornados has to deal with hundreds of simultaneous differential equations. • Differential cryptanalysis is concerned with factoring large prime numbers, requiring hundreds or thousands of machines cooperating on the solution (e.g., the recent breaking of DES using hundreds of machine in the Internet).
Important criteria of programming languages • universal. • reasonably natural for solving problems. • capable of being implemented on a computer. • capable of efficient implementation. • portable. • verifiable. • understandable.
Programming Language Design • A special purpose language • designed for a specific class of applications. • http://www.idiom.com/free-compilers/ECATEGORY/specialp-1.html • A general purpose language • applied to a wide range of applications.
Criteria in a good language design • Writability: The quality of a language that enables a programmer to use it to express a computation clearly, correctly, concisely, and quickly. • Readability: The quality of a language that enables a programmer to understand and comprehend the nature of a computation easily and accurately. • Orthogonality: The quality of a language that features provided have as few restrictions as possible and be combinable in any meaningful way. • Reliability: The quality of a language that assures a program will not behave in unexpected or disastrous ways during execution. • Maintainability: The quality of a language that eases errors can be found and corrected and new features added.
Criteria (Continued) • Generality: The quality of a language that avoids special cases in the availability or use of constructs and by combining closely related constructs into a single more general one. • Uniformity: The quality of a language that similar features should look similar and have similar. • Extensibility: The quality of a language that provides some general mechanism for the user to add new constructs to a language. • Standardability: The quality of a language that allows programs written to be transported from one computer to another without significant change in language structure. • Implementability: The quality of a language that provides a translator or interpreter can be written. This can address to complexity of the language definition.
Programming Language Processing • Any system for processing programming languages, executing them, or preparing them for execution is called a language processor. • Language processors include translators and auxiliary tools like syntax-directed editors. • A translator that immediately executes a program is called an interpreter, while a translator that changes a program into a form suitable for execution is called a compiler. • In other words, interpretation is a one-step process, in which both the program and the input are provided to the interpreter and the output is the result of the interpretation as shown below.
© 2003 Brooks/Cole Publishing / Thomson Learning™ Figure 1.1 The interpretation process
Compilation • Compilation is at least two-step process, in which the original program (source program) is input to the compiler, and a new program (target program) is output from the compiler. The compilation steps can be visualized as the following.
© 2003 Brooks/Cole Publishing / Thomson Learning™ Figure 1.2 The compilation process
Machine Languages • Regardless of the programming language that you are using, it is still a symbolic language that has to be translated into a form that the computer can execute. This encoded form is called the machine language. For example, for the execution of the assignment statement • BA2 • a typical sequence of machine code instructions might be as the following
Machine codes • Operation Register Tag Memory Address • 0001 01 00 0000 0000 (load) 0001 01 00 0000 0000 • 0011 01 10 0000 0010 (add) 0011 01 10 0000 0010 • 0010 01 00 0000 0100 (store)0010 01 00 0000 0100
Low-Level Languages • In programs written in a low-level programming language, each symbolic instruction can generate one machine instruction. An assembly language is a low-level language. • For example, for the assignment statement • BA2 • the following is a hypothetical assembly code into which the machine instructions might be translated: • MOV R1, A • ADD R1, #2 • MOV B, R1
© 2003 Brooks/Cole Publishing / Thomson Learning™ Figure 1.3 The assemble-link-execute cycle
High-Level Languages • A high-level programming language has the following characteristics: • Elementary data types and structures • Sequence control • Data control • Storage management • Operating environment • Machine architecture independence • Availability of program libraries
© 2003 Brooks/Cole Publishing / Thomson Learning™ Figure 1.6 The compile-link-execute cycle
To be continued • Programming a Machine versus Programming a Computation • Programmer Productivity • Programming Paradigms • Language Implementation
Programming a Machine versus Programming a Computation • In the early days of computing, computer scientists were really electrical engineers, physicist, and mathematicians. Engineers were primarily interested in making the machine do interesting things, whereas physicists and mathematicians were primarily interested in having the machine perform large-scale mathematical computations and give useful answers. • These computational problems had to be formulated precisely in the language of the machine, i.e., binary machine language. • In fact, the term “code” comes from the fact that a string of bits is an encoding of instructions to the computer.
Programming a Machine versus Programming a Computation • So, the electrical engineers all scratched their heads, and then invented assembly language! So, then you could program the machine at a higher level, but still inadequately as it is often very difficult to debug assembly language programs, and it is even more difficult to reuse code in other programs. Beside, compilers today are very good at generating efficient machine code from high level source code (e.g., C).
Programming a Machine versus Programming a Computation • Finally, a mathematically inclined engineer invented Fortran (Formula Translation). Thus was born the first popular high-level programming language for writing programs containing mathematical expressions, for example: • R = B**2 - 4.0*A*C Question: • what is the order of evaluation? • A compiler was implemented to translate these high-level statements and expressions into equivalent machine instructions that would correctly perform the desired computations.
Programming a Machine versus Programming a Computation • Many modern programming languages are descended from an intended replacement to Fortran, called Algol (for Algorithmic Language). Algol was the first language to introduce the idea of lexical scoping, which enabled the definition of modular procedures and the expression of recursive functions (like the factorial function). • Of course, today we still have Fortran, but Algol is gone! However, Simula was a successor of Algol, which influenced the design of object-oriented languages, such as Smalltalk, C++, and Java. • Lisp (List Processing) was originally a special purpose language developed for symbolic computation using lists. Scheme is a dialect of Lisp, but claims Algol as its “conceptual” ancestor because of the use of lexical scoping.
Programmer Productivity • Software engineers like to talk about “programmer productivity,” or how many Lines of Code (LOC), and number of bugs per line of code, etc. • A programming language can either encourage or discourage the introduction of errors. From an engineering perspective, we want to engineer error-free programs. This means the language needs to offer linguistic mechanisms that facilitate the production of reliable software.
Examples • Definition mechanisms • allowing the specification of clearly defined intent through the use of type declarations for both functions/procedures and data. • For example: type declarations and strongly typed function signatures mechanisms for defining independent lexical scopes to provide for modularization of a program’s procedures and data. • The ability to define libraries of subprograms, encapsulate data into Abstract Data Types (ADTs), and define interfaces as abstraction boundaris for the purpose of information hiding and localized access to data (i.e., no global data) are all critical elements of cleanly organizing a program.
Examples • The ability to share/reuse/extend abstract data types and/or functions/procedures. (e.g., abstract base classes and virtual functions in C++). • The ability to assert formal correctness statements about critical parts of a program and reason effectively.
Productivity • A program is intended to carry out a specific computation, but a programmer can fail to adequately address all data value ranges, input conditions, system resource constraints, memory limitations, etc. For mission critical applications, the programmer needs to be able to reason effectively about the behavior of a program. This means that the features of the language and their interaction should be clearly specified and understandable. If you do not or can not clearly understand the semantics of the language, your ability to accurately predict the behavior of your program is limited.
Programming Paradigms • “Paradigms” emerge as the result of social processes in which people develop ideas and create principles and practices that embody those ideas. The term paradigm comes from the book, “The Structure of Scientific Revolutions” by Kuhn. • Programming paradigms are the result of people’s ideas about how programs should be constructed, and the development of formal linguistic mechanisms for expressing those ideas, and software engineering principles and practices for using the resulting programming language.
Imperative Programming • Programming with • algorithms+data structures+assignment. • Programs consists of actions to effect changes of state, principally through assignment operations. • Imperative languages: Fortran, Algol, Cobol, PL/I, Pascal, Modula-2, Ada, C, have traditionally dominated in practice
Object-Oriented Programming • Imperative programming with objects+classes+inheritance. • OO programming is not necessarily imperative programming, but in practice most OO languages have been imperative: Simula, Smalltalk, C++, Modula-3, Java. However, CLOS (Common Lisp Object System) is an object-oriented version of Lisp.
Functional Programming • Programming with functions+lists minus assignment • Not all functional languages are “pure” (i.e., without the assignment statement). Practical functional programming languages adopt the functional style, but for practical reasons, have to rely on non-pure functions for input/output. You can’t completely escape the machine!
Logic Programming • Programming with propositions+predicates+logical deduction • Prolog and special theorem proving languages are designed for special purposes
Concurrent Programming • Programming with shared data+synchronized execution. • Concurrent programming cuts across imperative, object-oriented, and functional programming.
Extension Language Programming • Programming with scripts. E.g, Perl, Python, Tcl, ASP, etc.
Language Implementation • There are three basic approaches to translating and executing a program written in a high-level language into a form that can be executed by a machine. • Translation to machine code using a native-code compiler, and execution on a real machine. • Translation to bytecodes using a bytecode compiler, followed by execution on a “virtual” machine. • Translation into an internal form and execution via a read-eval-print interpreter.
Hybrid approaches • For example, the original C++ implementation from AT&T Bell Labs was a translator that first translated C++ to C, which was then compiled into assembly language, which was then assembled into machine code and executed. • New types of bytecode compilers have appeared in recent years, which are called Just-In-Time (JIT) compilers. JIT compilers translate compiled bytecodes into native machine code the first time the bytecode is executed by the virtual machine. Subsequent requests to execute the same bytecode sequence result in the native code being executed, resulting in a significant speedup in execution. • Although not always the case, most compiled languages are statically typed, meaning that type checking is done at compile-time. • Interpreted languages are often dynamically typed.
Static typing • Generally deemed “safer” since type errors can be detected early, at compile-time, before a program is executed. • Static typing means that the type of a variable is determined at compile-time and that type constrains the set of values that the variable can hold at run-time.
Dynamic typing • Done at run-time, so programmer type errors are not detected until the program is executed. • This implies that a type error in an infrequently executed part of a program may not be discovered for a long time, and only surfaces in an unusual (but critical) situation, which then causes the program to fail. Dynamic typing means that a types are associated with values at run-time, and the type of a variable dynamically changes during execution to conform to the type of the value that is currently being referenced by the variable.
Summary • Programming Languages • Programming Language Design • Programming Language Processing • Programming a Machine versus Programming a Computation • Programming Productivity • Programming Paradigms • A Brief History of Programming Languages • Language Implementation