Is there only one way to write computer programs? Of course not, you can implement the same algorithm in several ways or you can use several different programming languages.
Is the way you are thinking the same in same of every programming language? Not really, each language provides different opportunities which are making a difference in the way of your thinking. Sometimes these differences are pretty small, but sometimes they are really big.
Let’s take C and C++ as an example. They syntax is almost the same, in C++ you can do whatever you can do in C. But the style how most programmers are using C and C++ is slightly different. Since in C you can organise your code only by functions/methods, C++ is supporting classes and objects as well. And it makes it possible to build up your programs in a slightly different way, where your main blocks are classes. At the end of the day both programs are doing the same, but the way of thinking behind them is totally different.
C is a purely procedural programming language, since C++ is supporting multiple programming paradigms, like procedural and object oriented programming and it also gives you the opportunity to use some functional programming-like programming style.
Both procedural and object oriented programming are imperative programming paradigms. In case of imperative programming, you are telling your program step by step what it should do, like: create a variable, assign a value to that, print that value to the screen etc.
The way is not to tell the steps, just tell what you expect from your program, you are just describing its logic. It can be also done in multiple ways, you use the functional programming paradigm or the logic programming.
There are programming languages which are only supporting one dedicated programming paradigm, like Haskell is purely functional, or Prolog is supporting only logic programming, but there are also languages supporting multiple paradigms, like C++.
Most programmers meet first with imperative paradigms. In case of imperative programming you are using statements, which are running in a specified order and these statements are changing the state of your program. Like changing the value of variables etc. Based on how these statements are organised we can talk about procedural or object oriented programming.
In case of procedural programming we are defining procedures (subprograms) and then we are calling them in a specified order, with specific parameters. The subprograms can also call each other. Most well-known examples are C, Basic or Pascal.
In case of object oriented programming the basic elements of your program are objects. Objects are encapsulating data and related algorithms. The similar objects can be organized into classes. Object oriented programming should support the following principles: encapsulation, abstraction, polymorphism and inheritance. To do proper object oriented programming you can follow principles like SOLID or use design patterns. Most popular object oriented languages are JAVA and C#.
I also have to mention that the programming paradigm is not only about the language your are using. You can also write programs in JAVA, which are not really object oriented (by writing all code into the same class) and you can also imitate object oriented programming in C.
So it is much more about the way how you are thinking while writing your program.
The other concept is declarative programming. In this case you are not describing your program step by step, but you are describing it in a similar way to mathematical logic. In this case you have no direct control over the state of your program, so you can not change any parts of the state which an unrelated to your computation, which are out of the scope of your code. Such modifications of the state are called side effects and they are a source of a lot of bugs in case of imperative programming. In case of imperative programming you are avoiding side effects.
There are multiple style of declarative programming, just like functional programming, logic programming or database programming.
Logic programming is based on formal logic. The most popular logic programming languages are Prolog, ASP and Datalog.
This is a short example written in Prolog:
sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).
parent_child(X, Y) :- father_child(X, Y).
parent_child(X, Y) :- mother_child(X, Y).
Functional programming has been introduced with the programming language Lisp in the late 50’s. Nowadays this paradigm is becoming more and more popular. It is supported by programming languages like Haskell, Erlang, F# or Clean. But more and more modern programming languages are supporting it by new language elements, like lambda functions. So it is always possible to write functional style programs in languages like Java, C#, C++ or Python.
For the first look functional programming can be a bit strange for the ones who used to do only imperative programming before. Functional programming is based on lambda calculus. In functional programming you are using only functions without side effects. That means you can not modify the state of the memory directly, you can only calculate the value and return it. Then by using technologies like recursion, currying or higher order functions you can build up your whole programming from functions. For the first most likely it looks first. Let’s see some examples for some problems.
The below examples are written in Haskell.
This is a classical program which can be solved in both iterative and recursive way in case of imperative programming. In case of functional programming we will use of course the iterative way.
Code in haskell:
factorial n = if n < 2 then 1 else n * factorial (n-1)
Map is a function which is expecting a function and a list as parameters and it calls the function for each element of the list. It is a bit like using a cycle in case of imperative programming.
This is the implementation in haskell:
map f xs = if null xs then  else f (head xs) : map f (tail xs)
So in case if an empty list it is returning an empty list, otherwise it is calling the function for the head, which is the first element of the list, and then calling himself on the tail, which is the list without head.
As a last example: check if a list containing a dedicated item. It would look like this:
find _  = False
find x (x:xs) = True
find x (_:xs) = find x xs
So in case of empty list the answer is false. If the first element of the list is the one we are looking for it is returning true. Otherwise it is calling the same function for the list without it’s first element.
Next to the purely functional languages most of the well-known, modern languages support some elements which are making it possible to write code in functional style. These are mostly the lambda expressions and passing functions as parameters.
In C# Lambda expressions are supported. You can also pass functions as parameters by using delegates. The predefined Func template delegate makes it really easy. Using functional style of programming can be really useful by using LINQ or just at working with collections (foreach, filter etc.).
The below example is solving the factorial problem in C# using a functional way of programming by using the Func delegate and lambda expressions:
Func factorial = null;
factorial = x => x <= 1 ? 1 : x * factorial(x-1);
In python it is pretty easy, since it is using weak typing and it is possible to pass functions as arguments just out of the box. Lambda functions are also supported.
This style of programming in Python can be especially useful while working with data processing.
The factorial example in python:
fact = lambda x: 1 if x == 0 else x * fact(x-1)
Modern C++ also supports both lambda functions and passing functions as parameters (by using std::function), so I thought everything is given to write programs in a functional style. Then I went a bit deeper and I realised one thing which made it impossible: I couldn’t find a clear way to do a recursive call from a lambda function. There are some hacks and tricks which make it possible (like using template functions etc.), but none of the solutions are clear enough to use as a suggested way.
My other idea was to use the good old preprocessor directives to write functional-like programs in C++, but it there the issue was the same. There was no way to do a recursive call from the macro.
An other declarative paradigm is database programming. A good example is the SQL. Most of programmers knows it, but never thought that it is a declarative language. You can describe what would you like to do with the data in the database, but you don’t define how to do it.
There are several different styles of programming which have an influence on the way you are thinking. Different programming languages support different paradigms, each paradigm has its own area, specialities, advantages and disadvantages.