[ANU] [DCS] [COMP2100/2500] [Description] [Schedule] [Lectures] [Labs] [Homework] [Assignments] [COMP2500] [Assessment] [PSP] [Java] [Reading] [Help]
COMP2100/2500
Lecture 29: Comparison of Programming ParadigmsSummary
A discussion of object-oriented, procedural, scripting and other classes of programming languages; what they're good for, what they're not...
Outline
Object-oriented languages.
Comparison between Eiffel and Java.
Procedural languages.
Comparison between procedural and object-oriented languages.
Scripting languages.
Other paradigms.
Functional programming in Haskell.
Introduction
In this course we have covered languages of three fundamentally different types:
Object Oriented languages: Java.
Procedural languages: C.
Scripting languages: Bash.
There are other, radically different, programming paradigms.
Object Oriented languages
Object Oriented Languages Include:
Java
Eiffel
C++
Object Pascal (Delphi)
Smalltalk
Modula 3
Characteristic Features of OO languages:
A class is used to describe a data-structure, and the queries and commands used to inspect and update it.
Multiple objects then can be created as instances of a class.
Classes are organized into a hierarchy.
A new class can be defined by describing how it extends one (or more) existing classes from which it inherits.
Java and Eiffel: Differences within a Paradigm
class COUNTER creation reset feature {ALL} number: INTEGER -- number counted increment is -- count another one do number := number + 1 end reset is -- reset to zero do number := 0 end end -- class COUNTERpublic class Counter { private int num; public Counter() { num = 0; } /** number counted */ public int number() { return num; } /** count another one */ public void increment() { num++; } public void reset() { num = 0; } }
Java and Eiffel: Feature Comparison
Major feature comparison:
Feature Eiffel Java Multiple Inheritance + - Generic Types + - Design by Contract + - Overloading - + Java makes a distinction between the concepts of subtyping (using the implements keyword) and inheritance (using the extends keyword). A class can be a subtype of another class, without inheriting its implementation. Eiffel doesn't have this distinction.
Minor feature comparison:
In Java, features may be associated with a class as well as with an object.
In Java, inner classes may be defined inside a class to hold private data. (Coming versions of Eiffel will have this too.)
In Java, private features are hidden from subclasses, in Eiffel they are visible.
Procedural languages
Procedural Languages Include:
C
Pascal
FORTRAN
COBOL
Modula 2
Ada
Characteristic features of Procedural languages:
Data structures may be defined, and commands and queries defined on them. But they are not combined into a single conceptual object.
Data is passed to commands or queries for operation. For example in C: reset(&car_count); vs Eiffel: car_count.reset or Java: carCount.reset();
Data structures and related commands and queries may be grouped in some languages, called modular languages. These include Modula 2 and Ada.
C Programming Example
Header: counter.h typedef int counter; /* reset to zero */ extern void reset(counter *c); /* count another one */ extern void increment (counter *c);Implementation: counter.c #include "counter.h" /* reset to zero */ void reset(counter *c) { *c = 0; } /* count another one */ void increment(counter *c) { *c = *c + 1; }
If data is to be modified, a pointer must be passed.
The module and its signature are maintained in separate files.
Object Oriented and Procedural: Feature Comparison
Feature Object Oriented Procedural Abstraction through subtyping + - Reuse through Inheritance + - Encapsulation of data + -* Automatic Memory Management +** - *: is supported by modular languages
**: not supported by all OO languagesBut the news is not all good for OO languages:
Subtyping brings a loss of performance. Consider the call target.feature. The type of the object target, and therefore the appropriate implementation of feature, may have to be resolved at runtime. (This is called dynamic despatch, and trying to remove it is a major goal of compiler writers for object-oriented languages.)
Automatic memory management also brings a loss of performance (of course with a corresponding elimination of many horrible defects: segmentation faults, memory leaks, etc).
The conception of everything as an object is not always appropriate.
Object-oriented languages are not completely replacing procedural
Procedural languages remain the more appropriate choice in application areas where:
the data abstractions are simple
the need for speed is paramount
the developers can make use of a large infrastructure investment (extensive libraries and trained staff)
For example:
FORTRAN remains the dominant language for scientific computation.
C remains the dominant language for embedded programs and operating systems.
New business applications continue to be written in COBOL.
Scripting
Scripting languages include:
C Shell
Bourne Shell
Perl
Tcl
Characteristic features of scripting languages:
Variables do not need to be declared before they are used.
All data is represented as strings.
Literal strings do not need to enclosed in special markers (quotes). Almost everything else does (for example in Bash: ${x} for variables, $[1+2] for arithmetic expressions etc).
Few (or primitive) features for structuring programs or data.
Programs are interpreted rather than compiled.
When Would You Use a Scripting Language?
When the task
is not logically complex;
requires a great deal of string and text manipulation;
can be accomplished largely by running existing programs if you can control their options, input and output;
requires the manipulation of many files.
Scripting languages (particularly Perl) are now used extensively to generate dynamic web pages.
Other Programming Paradigms
There are other, radically different, ways to program:
Stack Languages
FORTH
PostScript
Database Query Languages
SQL
Logic Programming Languages
Prolog
Functional Programming Languages
Haskell
Miranda
ML
Lisp
Introduction to Functional Programming in Haskell
Functional programs only have functions that return results to their callers. There is no “flow of control” in the sense we're used to from Java, C or Bash.
There is no sense of “this happens first, then that”.
Everything is just a function.
Functions can act on and return complex data types.
There are no variables or assignment statements in functional programs. No values are ever modified.
There are no loops in functional programs. Recursion is used instead.
Data-types are defined separately from the functions that manipulate them. A generic stack type is defined as follows:
data Stack t = Empty | Push t (Stack t)A stack is defined to be either the constant stack Empty, or the result of the constructor Push that takes an element and a stack. The following are all valid stacks:
Empty
Push 1 Empty
Push 2 (Push 1 Empty)
Push False (Push True Empty)
Functions can now be defined by pattern matching on the different kinds of stack:
is_empty :: (Stack t) -> Bool is_empty Empty = True is_empty (Push x s) = False depth :: (Stack t) -> Int depth Empty = 0 depth (Push x s) = 1 + depth sFunction definitions need not be exhaustive: top and pop are not defined for empty stacks. (This avoids having to state preconditions like in Eiffel, write error-handling code or special cases...)
top :: (Stack t) -> t top (Push x s) = x pop :: (Stack t) -> (Stack t) pop (Push x s) = sNote that pop is not a procedure that modifies an existing stack, instead it is a function that makes a new stack from an old one. (We did something like this in Stack Version 3.)
Expression Trees in Haskell
data Expression = Constant Int | Sum Expression Expression | Product Expression Expression value :: Expression -> Int value (Constant n) = n value (Sum a b) = (value a) + (value b) value (Product a b) = (value a) * (value b) toStringInfix :: Expression -> String toStringInfix (Constant n) = show n toStringInfix (Sum a b) = "(" ++ toStringInfix a ++ "+" ++ toStringInfix b ++ ")" toStringInfix (Product a b) = "(" ++ toStringInfix a ++ "*" ++ toStringInfix b ++ ")" toStringPostfix :: Expression -> String toStringPostfix (Constant n) = show n toStringPostfix (Sum a b) = toStringPostfix a ++ " " ++ toStringPostfix b ++ " +" toStringPostfix (Product a b) = toStringPostfix a ++ " " ++ toStringPostfix b ++ " *"
Evaluation of Functional Programming
The expression tree just presented offers equivalent power to a Visitor pattern style implementation of expression trees in Eiffel.
+ The Haskell code is much shorter than the equivalent Eiffel code.
+ The Haskell code is significantly easier to follow.
- Few problems suit functional programming as well as recursive data-types do.
- Functional programs are usually relatively slow.
+ Functional programs are easier to reason about mathematically.
The Big Picture
There are a variety of significantly different programming paradigms:
Languages within a family are broadly similar: you should now be able to teach yourself the basics of any object-oriented, procedural, or scripting language within a few weeks!
The differences between language families can be significant.
By the time you graduate you will have had more exposure to other language families. By that time you should be able to consider what programming paradigm best suits a given problem.
[ANU] [DCS] [COMP2100/2500] [Description] [Schedule] [Lectures] [Labs] [Homework] [Assignments] [COMP2500] [Assessment] [PSP] [Java] [Reading] [Help]
Copyright © 2005, Jim Grundy & Ian Barnes, The Australian National University
Version 2005.1, Wednesday, 25 May 2005, 12:15:00 +1000
Feedback & Queries to
comp2100@cs.anu.edu.au