Programming Paradigms
Note: There are other programming paradigms, also important in computer science. We do not explain these paradigms yet. You will learn specific programming paradigms when you study individual programming languages.
- Logic programming.
- Procedural programming,
- Imperative programming,
- Declarative programming,
- Aspect oriented programming,
Examples:
- Fortran is a pure structured language,
- Algol is a pure procedural language,
- Python is multi-paradigm language,
- Ruby is a pure Object Oriented language,
- Lisp is first functional language,
- Haskel is pure functional language,
- SQL is pure declarative language,
- Prolog is pure logical programming language.
Linear Programming
In linear programming we can have a sequence of steps that can be executed or interpreted one by one until the program is finished. The program has a single start point and execute all steps in the program. There is no exception, no jump and no skip. The program always has the same effect when is executed.
Linear programming is used in Computer Science for data-oriented languages, document-oriented languages, and programming of legacy CNC machines in the manufacturing industry. In the past, knitting machines used patterns that were essentially linear programs that could repeat in loops.
XML Syntax
XML stands for Extensible Markup Language. It is a data-oriented language. It is not a Turing complete language, so you cannot make programs to solve computation problems. However, XML-based scripting languages exist, such as Apache ANT.
XML Element Anatomy
Example:
In the next example you can investigate a message file, stored as XML.
<!-- secret message XML example -->
<note>
<to>John</to>
<from>Marica</from>
<heading category="secret">Secret Message</heading>
<body>Please let's meet in the balcony.</body>
</note>
XML Structure
The core idea behind XML is markup. Markup consists of two symbols that enclose a tag, which looks like this: "<tag>". Unlike other languages, XML does not have pre-defined keywords. Instead, every organization or developer can define specific keywords for a particular domain. Therefore, this language is called extensible because it is continuously developed and enhanced by third parties.
XML Elements
In the example above you can see the XML is hierarchic. First line is a comment. You can ignore the comments. The is a tag used to start one element. The element has an end tag . This is the end of the element. Between the start and end of an element you can store the "content" of the element, explained below:
Element Content
The content of an element can be plain text or other elements. The elements can be side by site (siblings) or nested one inside the other on any number of levels. For example <to> is a child elements of <note> that is the root element. The root element contains all other elements.
Element Attributes
The attributes of an element are enumerated after the element name and before the closing markup ">" separator. For example, category="secret" is an attribute named category with the value secret. Values are always enclosed in double quotes. An element can have no attributes, one attribute, or several attributes. Sometimes an attribute has no value, which is called a Boolean attribute. If present, it has the value True; if absent, it has the default value False.
Structured Programming
In structured programming we create a complex, application based on nested blocks of of code called block statements. Using these structures we can avoid spaghetti code, specific to linear programming. The following structures are most popular in any imperative programming language:
- Decision: Create one block that is executed or not depending on one condition.
- Repetition: Create a block of code that is repeated several times
- Selection: Create a block selector based on a value with many cases
Decision
It is usually created with "if-then-else" keywords in most languages, but also can be created with "when" keyword in Bee and EVE languages. Consist in one condition and two blocks of code. The condition can be a logical expression, but in some languages can also be an expression that is (= 0 or >0) or maybe (null and not null). You can analyze the diagram to understand how is working:
Decision Diagram
Repetition
In structured programming there are many versions of repetitive statement. The idea is simple. We start a block of code with a condition. Then we repeat the block of code until the condition become false. The condition can be a simple logical expression.
Repetition Diagram
Selection
The selection statement has many blocks, represented in next picture by numbers: {1,2,3,4,...0}. This statement is sometimes called "switch" other times "case" or "match" or even "check". No matter how is called it does almost the same thing. It uses one value to "select" a path of execution.
Switch Diagram
Usability:
Using structured programming we can create Turing complete languages. These languages can do several operations that are represented in structured programming by statements with the following properties:
- Start with an initial state;
- Can ask for input;
- Can change it’s internal state;
- Can make decisions;
- Can execute one sequence of code or another;
- Can repeat a sequence of code one or many times;
- Can have one or more final states;
Object Oriented
This programming style introduce the idea that data and operations that can apply to data are tight connected. In pure Object Oriented programming we have only one things to define: Classes. Each class can hold several fields (attributes) and methods. The methods can change value of attributes.
Class Anatomy
Usability
You can use a class as a collection of methods. We can also create multiple "instances" of the class. Each instance is called an object. An object has the same attributes as the class and the same methods. For each object, we can set and modify the attribute values.
To understand better, we can compare the class with a cookie cutter. Each cookie we cut is an object created with the same template (the cutter). All cookies are almost the same, except if we sprinkle them with different colored candies. Then the cookies become a little different from each other.
Principles
Object-oriented programming has four principles, called the pillars of OOP. These principles are implemented by Java, Scala, and others à la carte. Python and PHP are also object-oriented languages.
| Abstraction | you can define abstract classes and interfaces | |
|---|---|---|
| Encapsulation | you can define public and private properties and members | |
| Inheritance | one class can inherit properties and methods from parent class | |
| Polymorphism | one method from a parent class can be overwritten in a child class. |
Abstraction
For implementing this principle, most languages enable the creation of classes. A class is a block of code that has a name and defines a scope. Within its scope, you can define data (fields) and functions (methods). Together, these are called "members" of the class.
Members of a class are more or less protected. You can define public members that are visible from outside the class and private members that are visible only inside the class scope (local members).
A class can contain logic (subroutines) usually called "methods". These subroutines can be more or less visible from outside the class scope. Methods can be private or public.
Sometimes we implement methods only partially. We define "abstract" methods. A class that has "abstract" methods is also "abstract". We cannot use abstract classes until they are fully implemented by a sub-class. Check the Inheritance principle to see what a sub-class is.
Encapsulation
Encapsulation in object-oriented programming is a mechanism of wrapping data (properties and attributes) and code acting on the data (methods) together as a single unit. Declaring the variables of a class as private strengthens encapsulation.
Classes can be "instantiated." That means we clone a class using a special method called a "constructor". The instances of a class are called "objects" or "instances" of the class. Each object can contain (encapsulate) different data or properties.
A class can implement special "static methods" or "static fields". These are members of the "class scope" that are unique and can be used without creating an instance of the class. Static fields do not represent data but rather "class settings" or "class states".
Inheritance
In languages that implement OOP à la carte, you can define one class based on another class. This mechanism is called Inheritance. All classes are derived from a primary class that is the root class. In other words, a class can "extend" another class.
Polymorphism
When we use Inheritance, a derived class "inherits" all properties and methods from the base class. Sometimes we can "overwrite" a method to change the default behavior of the base class. This allows us to extend and modify a class to create a different class with similar but not identical behavior. This is called polymorphism.
To take advantage of polymorphism, we can have a reference to an object using the parent class type. If we call a method, the object's method responds, not the parent class method. This way the method becomes polymorphic. It changes with the object type.
Advanced Features
Diverse OOP languages may offer other features. These features enhance even farther the capability of programmers to create reusable and reuse code made by other developers. However, learning these features require additional effort. Let's define these features:
Generics
Generics are classes that are not specific to a particular data type. For example, a dynamic list has the same logic but can be applied to different primitive types: List of integers, List of floats, and List of Double. In this case, we can use a generic library to create a specific List.
This mechanism was created to relax the strong typing paradigm. It reduces the number of lines of code we need to write for a specific design pattern. For dynamically typed programming languages, this is not necessary since a particular object or data member can have any data type.
Interfaces
Interfaces are "abstract" concepts that enforce specific behavior. Interfaces are almost the same as "abstraction," except that one class can implement multiple interfaces but can extend only one abstract class. That's the main difference.
An interface typically has all methods abstract in older Java versions. Now you can create methods that have a default implementation in an interface. However, most developers use abstract method declarations for interfaces.
Mix-ins and Traits
Some object-oriented computer languages enable you to inherit new features from multiple base classes. This is called multiple inheritance. Most commonly, however, OOP languages like Java, Scala, and Ruby do not support multiple inheritance. Another approach was found to enable developers to reuse code from multiple ancestors.
A mix-in is a class that reuses multiple "components" to simulate multiple inheritance. The components are called "traits" and represent namespaces. You can include multiple traits in a class to inherit all methods and variables defined in a trait. In Ruby, there are modules instead of traits.
Functional Programming
Some of the key concepts and terms used in functional programming include:
- Function: A function is a mathematical expression that takes one or more inputs and produces one output.
- Pure function: A pure function is a function that has no side effects. This means it always produces the same output for the same input.
- Immutable data: Immutable data is data that cannot be changed. This makes it easier to reason about programs and to test them.
- Lazy evaluation: Lazy evaluation is a technique that evaluates expressions only when they are needed. This can improve the performance of programs.
- Higher-order function: A higher-order function is a function that takes other functions as arguments. This allows for a great deal of flexibility in programming.
- A closure is a function defined inside another function. Closures are function instances created by higher-order functions.
- Callback functions are functions used as arguments to other functions. A callback is called later by another function. Lexical context is the local scope context for closures. This is bound to a closure. Lexical context enables the creation of function states.
- Generators are functions that yield new values for each call. You can use generators to create IDs for items, generate elements in a set, or create an iterative statement.
- Recursive functions are functions that call themselves multiple times with different arguments. Tail optimization is a way to optimize a recursive function in a specific way.
- Lambda functions are pure, deterministic functions based on a single expression. Pure functions do not have side-effects. A stochastic function returns random results. A deterministic function produces the same result for the same input.
Every functional programming language needs functions to be powerful enough to support this paradigm. Before discussing details, let's learn about functions.
Function
Function Concept
Languages
Functional programming is back and stronger than ever. It is superior to Object Oriented paradigm but harder to understand at first. Therefore new programming languages are combining Object Oriented, Functional Programming and Structured Programming.
Functional programming languages are designed around mathematical functions that use conditional expressions and recursion to perform computation. Unlike classic programming, functions are "first-class citizens" in functional languages. All sub-programs are functions. Some of the popular functional programming languages include:
- Lisp,
- Haskell,
- Clojure,
- OCaml,
- Rocket,
Scope Model
Dynamic Scope is created at execution time, while Static Scope is created with the function and remains in memory as long as the function is available. This approach makes functions behave like objects. In functional programming, functions are called "first-class citizens". Functions can have states, which is the main difference between structured programming and functional programming.
Functional Features
Using static scope enable some interesting features that makes functional programming exciting and efficient. Some of these features are:
- A function can be assigned to a variable as a reference;
- A function can receive a reference to a function as parameter;
- A function can produce as a result, another function;
- A function can be suspended in memory and resumed later;
- A function can have states (sometimes called attributes);
- You can chain several functions using dot notation;
- You can create a collection of function references;
Advantages
Functional Programming is more efficient and more safe especially useful for concurrent programming. Modern computers are using multi-core processors that enable execution of functions in parallel to improve performance. This is why modern programming languages are using Static Scoping and Functional Programming.
Pure Languages
Pure functional languages are harder to accept. Some languages that I have study are very different than classic languages. There are some special features that are more than I can handle. Some features of functional programming is implemented in so called hybrid languages or multi-paradigm languages, that I like more.
In these languages functions do not have unexpected “side effects” that could potentially modify or influence the result or the behavior of other functions. However these languages do not have classic control flow statement like loops and selection statements. Instead you can use expressions and recursive functions to resolve problems and this was difficult for me.
Modern Languages
Modern programming languages are using Static Scoping. This make functions more deterministic but enable control flow statements to be used inside functions. My favorite new languages are these:
- Julia,
- Nim,
- Go,
- Swift,
- Rust,
Note: In recent versions of Java, we have seen the introduction of functional programming features. Java now has support for lambda functions, which are very useful for creating "callback functions" used in generic algorithms and parallel computing. Two alternative Java languages that implement functional programming fully and can also run on the JVM are Kotlin and Scala. Both are popular languages used in production.
References
A comprehensive glossary:fp-glossary
Conclusion
There are advantages and disadvantages to each programming paradigm. Therefore, many computer languages implement multiple paradigms. I find this to be a good approach. Now you are prepared to study the history, present, and future of computer languages. Congratulations, and read on!
Read next: Programming Languages