Declarative programming is a programming paradigm where you specify what the program needs to accomplish rather than how to accomplish as opposed with imperative programming. That is in simpler terms, imperative programs specify the sequence of steps/commands to be followed by the computer system where as declarative programs describe the logic of the program without specifying the control flow.
Declarative programming is widely used in logic programming and Prolog is a popular language inspired by many logic programming researches. Below are some example functions written using Prolog.
Reversing a List
Consider a function to reverse a given list of items. If this is to be implemented using imperative programming, we need to specify the compiler each step to be happened. But with Prolog, we just need to say what we want.
reverse_list([],[]). reverse_list([H|T],X) :- reverse_list(T,A), append(A,[H],X).
A Prolog procedures consists clauses and clauses can be either facts or rules. Facts are of the form
head.
Rules are of the form,
head :- t1,t2,…..,tk. (where k>=1)
So in our procedure to reverse the list, first clause is a fact which specifies that reverse of an empty list is an empty list. Second clause is a rule that specifies what is true about the result if it is not an empty list. The rule says reverse of the list [H|T] is X if X is the list obtained via appending H to the end of a list A, where A is the reverse of T. Here, [H|T] is the list notation in Prolog where H is the head element and T is the tail of the list.
If this is to be done in an imperative language, we may have to either traverse the given list until end or start traversing the list from end (if the language provide that functionality) and add each element to another list one by one.
Also, note that this works for any data item, numbers or strings or whatever, implicitly.
Below is an example invocation of the above procedure.
Below is an example invocation of the above procedure.
[1] 69 ?- reverse_list([1,2,3,4],X). X = [4, 3, 2, 1]. [1] 70 ?- reverse_list(['cat','bird','dog','lion'],X). X = [lion, dog, bird, cat].
Delete first occurrence of an item in a list
Below is the Prolog procedure to delete the first occurrence of an item in a list.
delete_first(H,[H|T],T). delete_first(X,[H|T],[H|Y]) :- X\==H,delete_first(X,T,Y).
In the above procedure, first clause is a fact which specifies that if the element we want to delete is the head of the list, result is simply the tail of the list. Second clause is a rule that specifies if item X is removed from the list [H|T] result is [H|Y], if X is not equal to H and Y is the resultant list when X is deleted from tail of the list [H|T].
?- delete_first(2,[1,2,3,4,5],X). X = [1, 3, 4, 5] . ?- delete_first('cat',['dog','lion','cat','bird','tiger'],X). X = [dog, lion, bird, tiger] .
Split a list into two lists that contain positive and negative numbers
Below is the Prolog procedure to split a list into two lists based on the sign.
split([],[],[]). split([H|T],[H|P],N) :- H>0,split(T,P,N),!. split([H|T],P,[H|N]) :- H<0, split(T,P,N).
First fact says that splitting an empty list to two positive and negative lists results two empty lists. Second clause is a rule which indicate that a list having head H and tail T is split into a positive list [H|P] and negative list N if H > 0 and P,N are the positive and negative lists of tail T. Third clause is the same rule when head is negative.
?- split([1,2,-1,4,7,-2,-4,8,-9],P,N). P = [1, 2, 4, 7, 8], N = [-1, -2, -4, -9].
From all the above examples we can clearly see how declarative programs differs from the programs we write in languages like Java, C, C++ etc. Declarative and imperative programming has distinguished application domains. Even though it looks like declarative programming involves less coding, it is not applicable for all the domains as it can be used only for very specific purposes.