You are on page 1of 18

Comparison between C\C++\Lisp\Prolog

Written by Ahmed Hesham Mostafa, secon 1, FCIH, Level 3, CS, 18/11/2009

  ‫ا ه



this article introduces the difference between Imperative , functional ,OOP and logic
programming languages by using example language for each type.


a programming paradigm that describes computation in terms of statements that change a

program state also called structured programming language. the program is built from one
or more procedures (also known as subroutines or functions) .I will use C programming
language as an example for it


programming paradigm that treats computation as the evaluation of mathematical functions

and avoids state and mutable data. I will use Lisp programming language as an example for it

OOP "Object Oriented language"

a programming paradigm that uses "objects" – data structures consisting of data fields and
methods together with their interactions – to design applications and computer programs.
Programming techniques may include features such as information hiding, data abstraction,
encapsulation, modularity, polymorphism, and inheritance. I will use C++ programming
language as an example for it

logic programming

Logic programming is, in its broadest sense, the use of mathematical logic for computer
programming. I will use Prolog programming language as an example for it

Data types between C, C++, Lisp, Prolog

A C language programmer has to tell the system before-hand, the type of numbers or
characters he is using in his program. These are data types. There are many data types in C
language. A C programmer has to use appropriate data type as per his requirement.

C language data types can be broadly classified as

Primary data type
Derived data type
User-defined data type

Primary data type

TYPE SIZE (Byres) Range

Char or Signed Char 1 -128 to 127
Unsigned Char 1 0 to 255
Int or Signed int 2 -32768 to 32767
Unsigned int 2 0 to 65535
Short int or Signed short int 1 -128 to 127
Unsigned short int 1 0 to 255
Long int or signed long int 4 -2147483648 to 2147483647
Unsigned long int 4 0 to 4294967295
Float 4 3.4 e-38 to 3.4 e+38
Double 8 1.7e-308 to 1.7e+308
Long Double 10 3.4 e-4932 to 3.4 e+4932

User defined type declaration

In C language a user can define an identifier that represents an existing data type. The user
defined datatype identifier can later be used to declare variables. The general syntax is

typedef type identifier;

here type represents existing data type and ‘identifier’ refers to the ‘row’ name given to the
data type.


typedef int salary;

typedef float average;

Declaration of Storage Class

Variables in C have not only the data type but also storage class that provides
information about their location and visibility. The storage class divides the portion of

the program within which the variables are recognized.

Auto: It is a local variable known only to the function in which it is declared. Auto is
the default storage class.

Static: Local variable which exists and retains its value even after the control is
transferred to the calling function.

Extern: Global variable known to all functions in the file

register: Social variables which are stored in the register.

TYPE SIZE (Byres) Range
Char 1 signed: -128 to 127
unsigned: 0 to 255
short int 2 signed: -32768 to 32767
unsigned: 0 to 65535
Int 4 signed: -2147483648 to
unsigned: 0 to 4294967295
long int 4 signed: -2147483648 to
unsigned: 0 to 4294967295
Bool 1 true or false
Float 4 +/- 3.4e +/- 38 (~7 digits)
Double 8 +/- 1.7e +/- 308 (~15 digits
long double 8 +/- 1.7e +/- 308 (~15 digits)
wchar_t 2 or 4 1 wide character


• Printed Representation and Read Syntax

The printed representation of an object is the format of the output generated by the Lisp
printer (the function prin1) for that object. The read syntax of an object is the format
of the input accepted by the Lisp reader (the function read) for that object.

• Comments

A comment is text that is written in a program only for the sake of humans that read
the program, and that has no effect on the meaning of the program.

• Programming Types

TYPE SIZE (Bits) Range

Integer 28 -134217728 to 134217727
Character 19 0 to 524287
Also contain these types :-Symbol Type , Sequence Types , Cons Cell and List
Types , Array Type , String Type , Vector Type , Char-Table Type , Bool-Vector
Type , Function Type , Macro Type , Primitive Function Type , Byte-Code Function
TypeAutoload Type .

• Editing Types

Type, Marker, Window, Frame, Window, Frame, Process, Stream.

Prolog's single data type is the term. Terms are either: atoms, numbers, and
Or compound terms (structures). The figure below presents a classification of the
data types in Prolog:

Atoms: An atom is a general-purpose name with no inherent meaning. It is

Composed of a sequence of characters that is parsed by the Prolog reader as single
Numbers: Numbers can be integers or real numbers (not used very much in typical
Prolog programming.
Variables: Variables are denoted by a string consisting of letters, numbers and
Underscore characters, and beginning with an upper-case letter or underscore.

Program structure in C\C++\Lisp\Prolog

#include <stdio.h>

int main()
/* My first program */
printf("Hello, World! \n");

return 0;

// my first program in C++

#include <iostream>
using namespace std;

int main ()
cout << "Hello World!";
return 0;

(+ 2 2) ; adds 2 and 2, yielding 4.

(defvar *x*) ; Ensures that a variable *x* exists,

; without giving it a value. The asterisks are
part of
; the name. The symbol *x* is also hereby endowed
; the property that subsequent bindings of it are
; rather than lexical.
(setf *x* 42.1) ; sets the variable *x* to the floating-point
value 42.1

;; Define a function that squares a number:

(defun square (x)
(* x x))

;; Execute the function:

(square 3) ; Returns 9
;; the 'let' construct creates a scope for local variables. Here
;; the variable 'a' is bound to 6 and the variable 'b' is bound
;; to 4. Inside the 'let' is a 'body', where the last computed value
is returned.
;; Here the result of adding a and b is returned from the 'let'

;; The variables a and b have lexical scope, unless the symbols have
;; marked as special variables (for instance by a prior DEFVAR).
(let ((a 6)
(b 4))
(+ a b)) ; returns 10


A Prolog program consists of a database of facts, rules, and queries. This program is,
in essence, a knowledge base.

• Fact: head but no body

• Rules: head and body
mortal(X) :- man(X).
• Questions: body but no head
Use ``;'' to get next possible answer, Return to end.
Yes means true with no variables, no means not consistent with database.

Data structure in C\C++\Lisp\Prolog


Declaration of arrays:
type variable-name[50];
for example: float height[50];
Initialization of arrays:
type array_name[size]={list of values};
int number[3]={0,0,0};
Multi dimensional Arrays:
two dimension arrays
data_type array_name[row_size][column_size];
int m[10][20];

a 3 dimensional array
date_type array_name[s1][s2][s3]…..[sn];
int survey[3][5][12];
float table[5][4][5][3];


struct lib_books
char title[20];
char author[15];
int pages;
float price;

struct lib_books, book1, book2, book3;


union item
int m;
float p;
char c;



Similar to C array


struct structure_name {
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
} object_names;


struct product {
int weight;
float price;
} ;

product apple;
product banana, melon;

NOTE:C++ is a OOP language so it has additional data structure types.

3-Object oriebted in C++:

(a) Classes
A class is an expanded concept of a data structure: instead of holding only data,
it can hold both data and functions.

An object is an instantiation of a class. In terms of variables, a class would be

the type, and an object would be the variable.

Classes are generally declared using the keyword class, with the following
class class_name {
} object_names;

• private members of a class are accessible only from within other members of
the same class or from their friends.
• protected members are accessible from members of their same class and
from their friends, but also from members of their derived classes.
• public members are accessible from anywhere where the object is visible.

// classes example
#include <iostream>
using namespace std;

class CRectangle {
int x, y;
void set_values (int,int);
int area () {return (x*y);}

void CRectangle::set_values (int a, int b) {

x = a;
y = b;

int main () {
CRectangle rect;
rect.set_values (3,4);
cout << "area: " << rect.area();
return 0;


Declaration of arrays:
(typep (make-array ... :element-type 'A ...)
'(array A)))
Initialization of arrays:
(make-array '(4 2 3)
'(((a b c) (1 2 3))
((d e f) (3 1 2))
((g h i) (2 3 1))
((j k l) (0 0 0))))


different structures may print out in different ways; the definition of a structure type
may specify a print procedure to use for objects of that type (see the :print-
function option to defstruct). The default notation for structures is

slot-name-1 slot-value-1
slot-name-2 slot-value-2

where #S indicates structure syntax, structure-name is the name (a symbol) of the

structure type, each slot-name is the name (also a symbol) of a component, and each
corresponding slot-value is the representation of the Lisp object in that slot.

Lists in Prolog
A list of terms can be represented betweenbrackets:[a, b, c, d] Its head is a and its tail is
[b, c, d].
The tail of [a] is [ ], the empty list.
Lists may contain lists:
[3.3, [a, 8, [ ]], [x], [p,q]] is a list of four items.
Special form to direct pattern matching:
• The term [X|Y] matches any list with at least one element:
X matches the head of the list, and Y matches the tail.
The term [X,Y,77|T] matches any list with at least three elements whose third element
is the number 77:X matches the first element,Y matches the second element, and T
matches rest of the list after the third item.
Using these pattern matching facilities, values can be specified as the intersection of
constraints on terms instead of by direct assignment.
Use variable names that are suggestive:
[ Head | Tail ] or [ H | T ]

Branching in C\C++\Lisp\Prolog

if Statement:

if (condition)

EX: if (i=1)

The If else construct: if (num < 0)

printf ("The number is negative")


printf ("The number is positive")

Compound Relational tests:

a> if (condition1 && condition2 && condition3)

b> if (condition1 // condition2 // condition3)

The syntax in the statement ‘a’ represents a complex if statement which combines
different conditions using the and operator in this case if all the conditions are true
only then the whole statement is considered to be true. Even if one condition is false
the whole if statement is considered to be false.

The statement ‘b’ uses the logical operator or (//) to group different expression to be
checked. In this case if any one of the expression if found to be true the whole
expression considered to be true, we can also uses the mixed expressions using logical
operators and and or together.

Nested if Statement

if (condition1)
if (condition2)

The ELSE If Ladder

if (condition1)
statement – 1;
else if (condition2)
else if (condition3)
else if (condition)

statement n;
default statement;

The Switch Statement:

Switch (expression)
Case case-label-1;
Case case-label-2;
Case case-label-n;
Case default

The GOTO statement:

goto label;
goto label;
#include <stdio.h> //include stdio.h header file to your program
main () //start of main
int n, sum = 0, i = 0 // variable declaration

printf ("Enter a number") // message to the user

scanf ("%d", &n) //Read and store the number

loop: i++ //Label of goto statement

sum += i //the sum value in stored and I is added to sum

if (i < n) goto loop //If value of I is less than n pass control to


printf ("\n sum of %d natural numbers = %d", n, sum)

//print the sum of the numbers & value of n



Similar to C but do not contain GOTO statement.



By using the convention that a zero value is false and a non-zero value is true, LISP
allows conditional branching and boolean logic.

The cond function takes a series of condition-result pairs. This construct is similar to
a Switch-Case block in C.


( defun abs-val(x)
(cond ( (< x 0) (-x) )
( (>= x 0) x )


The if function takes an expression to be examined as true or false, and returns one of
its two other parameters, depending upon the result.


(if (< x 0) (-x) x)

Boolean operators

The and and or functions act as boolean operators. Their left to right checking gives
rise to a side-effect which is often used as a conditional branching technique. and
stops checking when it encounters one item which is false, while or stops checking
when it encounters one true item.

if(Condition, TrueClause, FalseClause) :-
Condition, !, TrueClause;
!, FalseClause)

Prolog already has an "if_then_" operator:

Condition -> TrueClause; !, FalseClause

if(X, Y) :-
\+ var(X),
X is 1, % if this fails, prolog tries the next clause of if/2

Y is 0.

if(X, Y) :-
\+ var(X),
Y is 0.

?- if(0, A).
A = 1.

?- if(1, A).
A = 0.

Looping in C\c++\Lisp\Prolog
in looping process in general would include the following four steps
1. Setting and initialization of a counter
2. Exertion of the statements in the loop
3. Test for a specified conditions for the execution of the loop
4. Incrementing the counter

The While Statement:

while (test condition)
body of the loop

The Do while statement:


The Break Statement:


while(1) // While loop starts

scanf(“%d”,&I); // read and store the input number
if(I==-1) // check whether input number is -1
break; //if number –1 is input skip the loop
sum+=I; //else add the value of I to sum
num++ // increment num value by 1

Continue statement:


For Loop:

The for loop provides a more concise loop control structure. The general form of the
for loop is:
for (initialization; test condition; increment)
body of the loop


for(I=0;I < = 30; I+=2) //for loop

sum+=I; //add the value of I and store it to sum
sum_of_squares+=I*I; //find the square value and add it to
} //end of for loop
printf(“Sum of first 15 positive even numbers=%d\n”,sum);
//Print sum
printf(“Sum of their squares=%d\n”,sum_of_squares); //print


Similar to C


LISP has no loop constructs, so recursion is the only way to process data. A recursive
function is a function which calls itself. This technique recognizes that an operation
on some data may be best expressed as the aggregate of the same operation performed
on each item of data of which it is comprised. Obviously this technique is best used
with data structures which have the same form at both higher and lower levels,
differing only in scale.

This focus on recursion is the reason for LISP's popularity with AI researchers, who
often attempt to model large-scale behavior in terms of smaller-scale decisions. For
instance, recursion is often used in LISP to search state spaces.

Many of the lists used in LISP programs would be better referred to as trees. Lists are
simply the mechanism used to represent those trees.

The car and cdr functions are generally used to recourse (or 'walk') through the
elements in a tree, while cons is often used to gradually build tree structures to form
the result of a recursive operation. By also using the null function to test for an empty

list, we can walk through the tree structure, dealing with successively smaller pieces
of the tree.

car returns the first element of a list. e.g. ( car '(a b c) ) evaluates to a.

cdr returns the list with the first element removed. e.g. ( cdr '(a b c) ) evaluates to (b

cons are an associated function which is used to build tree structures, often to form
the result of a recursive operation. Note that it does not simply concatenate lists, but
undoes the effects of a hypothetical use of car and cdr. e.g. ( cons '(a b) '(c d e) )
evaluates to ( (a b) (c d e)) rather than (a b c d e).

Note that the use of these functions can lead to a great deal of inefficient copying.


1-looping using command repeate

write('Enter command (end to exit): '),
write(X), nl,
X = end.

The last goal will fail unless end is entered. The repeat/0 always succeeds on
backtracking and causes the intermediate goals to be re-executed.

We can execute it by entering this query.

?- command_loop.

We will write a new predicate called do/1, which executes only the commands we
allow. Many other languages have 'do case' control structures that perform this kind of
function. Multiple clauses in a Prolog predicate behave similarly to a 'do case.'

Here is do/1. Notice that it allows us to define synonyms for commands, that is, the
player can enter either goto(X) or go(X) to cause the goto/1 predicate to be executed.


NOTE: The cut serves two purposes. First, it says once we have found a 'do' clause to
execute, don't bother looking for anymore. Second, it prevents the backtracking
initiated at the end of command_loop from entering the other command predicates.

Here are some more do/1's. If do(end) did not always succeed, we would never get to
the' X = end' test and would fail forever. The last do/1 allows us to tell the user there
was something wrong with the command.

do(take(X)) :- take(X), !.
do(_) :-
write('Invalid command').

We can now rewrite command_loop/0 to use the new do/1 and incorporate puzzle/1 in
the command loop. We will also replace the old simple test for end with a new
predicate, end_condition/1, that will determine if the game is over.

write('Welcome to Nani Search'), nl,
write('>nani> '),
do(X), nl,

Two conditions might end the game. The first is if the player types 'end.' The second
is if the player has successfully taken the Nani.

end_condition(_) :-

The game can now be played from the top.

?- command_loop.

2-looping using recursion

Most interesting algorithms involve repeatingsome group of actions.

Prolog implements repetition using recursion.
Recursion is closely related to mathematical
induction, requiring two cases:
Basis: Solve some initial or small version ofthe problem directly.
Recursion: Assuming the algorithm works onsmaller or simpler versions of the problem,
solve an arbitrary instance of the problem.
sublist(S,L) succeeds if and only if the list S is asublist of the list L.
sublist([a,b,c], [a,b,c,d,e]) succeeds.
sublist([c,d], [a,b,c,d,e]) succeeds.
sublist([b,d], [a,b,c,d,e]) fails.

For list algorithms, the basis usually deals withan empty list, certainly the smallest list.
(Some algorithms for lists do not handle theempty list; so begin with a singleton list, [H]).
For the recursion step, we define the algorithmfor the arbitrary list, [H|T], assuming that it
works correctly for its tail T, a smaller list.

Sublist basis

The empty list is a sublist of any list.

sublist([ ], L). % 1

Sublist recursion

List [H|T] is a sublist of the list [H|U] if list T is a sublist of list U starting at the first
sublist([H|T], [H|U]) :- initialsublist(T,U). % 2
initialsublist([ ], L). % 3
initialsublist([H|T],[H|U]) :- initialsublist(T,U). % 4
Or the list S is a sublist of the list [H|T] if it is a
sublist of T.

sublist(S, [H|T]) :- sublist(S,T). % 5

These two cases correspond to the situation where the sublist begins at the start of the
list or the sublist begins later in the list, the only two possibilities.

Sample Executions

sublist([b,c,d], [a,b,c,d,e,f]) % 5
because sublist([b,c,d], [b,c,d,e,f]) % 2
because initialsublist([c,d], [c,d,e,f]) % 4
because initialsublist ([d], [d,e,f]) % 4
because initialsublist ([ ], [e,f]) % 3
sublist([b,d], [b,c,d]) fails % 2
because initialsublist([d], [c,d]) fails
and % 5
because sublist([b,d], [c,d]) fails % 5
because sublist([b,d], [d]) fails % 5

because sublist([b,d], [ ]) fails