A
computable set of steps to achieve a desired result.
A
detailed sequence of actions to accomplish some task.
Technically,
an algorithm must reach a result after a finite number of steps, regardless of
the input data. Therefore, an algorthm is a set of steps that is guaranteed to
terminate.
The
term is also used loosely for any sequence of actions (which may or may not
terminate).
Note:
The word comes from the Persian author Abu Ja'far Mohammed ibn Mûsâ
al-Khowârizmî who wrote a book with arithmetic rules dating from
about
825 A.D.
An
organization of information, usually in memory, for better algorithm efficiency,
such as queue, stack, linked list, heap, dictionary, and tree. It may include
redundant information, such as length of the list or number of nodes in a
subtree.
A
set of values with associate legal operations that may be performed on these
values, from which a variable, constant, function, or other expression may take
its value.
A
mathematically specified collection of data-storing entities with operations to
create, access, change, etc. instances.
Note: Since the collection is
defined mathematically, rather than as an implementation in a computer
language, we may reason about effects of the operations, relations to other
abstract data types, whether a program implements the data type, etc.
A
type whose internal form is hidden behind a set of access functions. Objects of
the type are created and inspected only by calls to the access functions. This
allows the implementation of the type to be changed without requiring any
changes outside the module in which it is defined.
Abstract
data types are central to object-oriented programming where every class is an
ADT.
One
of the simplest abstract data types is the stack. The operations new(), push(v,
S), top(S), and pop(S) may be defined with the following.
new()
returns a stack
pop(push(v,
S)) = S
top(push(v,
S)) = v
where
S is a stack and v is a value.
From
these axioms, one may define equality between stacks, define a pop function
which returns the top value in a non-empty stack, etc. For instance, the
predicate isEmpty(S) may be added and defined with the following two axioms.
isEmpty(new())
= true
isEmpty(push(v,S))
= false
A
decision problem that can be solved by an algorithm that halts on all inputs in
a finite number of steps. The associated language is called a decidable
language or a recursive language.
A
language for which membership can be decided by an algorithm that halts on all
inputs in a finite number of steps --- equivalently can be recognized by a
Turing machine that halts for all inputs. A decidable language is also called a
recursive language.
A
property of sets for which one can determine whether something is a member or
not in a finite number of computational steps.
Decidability
is an important concept in computability theory. A set (e.g. "all numbers
with a 5 in them") is said to be "decidable" if I can write a
program (usually for a Turing Machine) to determine whether a number is in the
set and the program will always terminate with an answer YES or NO after a
finite number of steps.
Most
sets you can describe easily are decidable, but there are infinitely many sets
so most sets are undecidable, assuming any finite limit on the size (number of
instructions
or number of states) of our programs. I.e. how ever big you allow your program
to be there will always be sets which need a bigger program to decide
membership.
One
example of an undecidable set comes from the halting problem. It turns out that
you can encode every program as a number: encode every symbol in the
program
as a number (001, 002, ...) and then string all the symbol codes together. Then
you can create an undecidable set by defining it as the set of all numbers
that
represent a program that terminates in a finite number of steps.
A
set can also be "semi-decidable" - there is an algorithm that is
guaranteed to return YES if the number is in the set, but if the number is not
in the set, it may either
return
NO or run for ever.
The
halting problem's set described above is semi-decidable. You decode the given
number and run the resulting program. If it terminates the answer is YES. If it
never
terminates, then neither will the decision algorithm.
Procedural programming
Functional programming
Declarative programming
Object-oriented programming
Module-based programming
Generic programming
1950
Fortran LISP – simbolic data and programs
– procedural abstractions - recursion, controled evaluation
- scientific computing - dynamic binding
- automatic garbage collection
1960
Algol-60 Cobol – file processing
Classes, object, event-driven computation
Simula Algol-68 PL/I
1970
Pascal – structured programming
Smalltalk – object-oriented programming Scheme – closures, continuations
C – variable level abstractization processing Common Lisp - standardization
Modula – modular programming Prolog – declarative programming
Ada – extended modularization
- exception handling, concurrency
1980
C++ - impure object-oriented programming ML – mathematical model, typed
Eiffel – OOP, correctness verification mechanisms
Caml, SML – OO functional prog.
1990
Java – OOP, concurrency, portability Haskell
CLIPS – declarative rules
Conventional procedural languages
Functional languages
3 Semantics
AS views the program as a state machine. Programming
language constructs are formalized by describing how their execution causes a
state change.
A state is described by a first-order logic
predicate which defines the property of the values of the program variables in
that state.
P
– postcondition = a predicate that is required to be true after the execution of a
statement S
Q
– precondition for S and P = a predicate that is required to be true before the execution of S
and guarantees that the execution of S terminates and postcondition holds upon
termination.
W
= the weakest precondition for a statement S and postcondition P, if any precondition Q for S and
P implies W.
AS
specifies each statement of a language in terms of a function asem
called the predicate transfer which yields the weakest precondition
W for any statement S and postcondition P.
asem(x=expr; , P) = Px® expr
asem(S1; , P) = Q
asem(S2; , Q) = R Þ asem(S1;
, P) = R
if B then L1 else L2
asem(if-stat, P) = (B É asem(L1; , P)) and (not
B É asem (L2; P))
2 Denotational semantics
DS associates each language statement with a
function dsem from the state of the program before the execution
to the state after execution.
The state is represented by a function mem
: ID ® V (ID = the set of variables, V = the set of
values)
Each
variable name is said to denote a value, e.g. mem(X)
the result of evaluating
expr after replacing
each variable V in expr with
mem(V)
mem(exp)
= or
error if mem(V) is undefined
error if mem(V) is
undefined for V
dsem(x=expr,
mem) = mem’, where mem’(y) = mem(y) for all x ¹ y
mem’(x)
= mem(expr)
dsem(S1,
mem) = mem1
dsem(S2,
mem1) = mem2 Þ dsem(S1;
S2; , mem) = mem2
if B then L1 else
L2
dsem(L1, mem) if mem(B) = true
dsem(if
B then L1 else L2) =
dsem(L2, mem) if mem(B) =
false
while B do L
![]()
mem if mem(B) = false
dsem(while
B do L, mem) =
dsem(while B do L, dsem(L, mem))
if mem(B) = true
Some supplements on typing
Strict
enforcement of type rules with no exceptions. All types are known at compile
time, i.e. are statically bound. With variables that can store values of more
than one type, incorrect type usage can be detected at run-time.
Strong
typing catches more errors at compile time than weak typing, resulting in fewer
run-time exceptions.
The
languages Ada, Java, and Haskell are strongly typed. Pascal is (almost)
strongly typed.
C
and C++ are sometimes described as strongly typed, but are perhaps better
described as weakly typed.
Strict
enforcement of type rules but with well-defined exceptions or an explicit
type-violation mechanism. Weak typing is "friendlier" to the
programmer than strong typing, but catches fewer errors at compile time.
C
and C++ are weakly typed, as they automatically coerce many types e.g. ints and
floats. E.g.