top of page

Doing It the Functional Way in C++

Safeguarding sensitive data.

I’ve spent some time with C++ for doing Competitive Programming in my graduation days. But I never got a chance to use C++ in my office projects, I was coding in Functional programming(FP) languages. But after 2 years, I got an opportunity to work on C++. As a Functional Programming enthusiast who is very much habituated to the cool FP style which makes the life of developers easy, I started exploring ways to code in FP style in C++. I learnt C++ has got amazing features in the latest releases. In this blog, we will go through the basics of functional programming, and what parts of it are possible in C++.

Identifying and fixing vulnerabilities.

Prerequisites:

  • A little experience in C++

  • A bit of experience with any Functional programming language or paradigm

  • A C++ compiler which supports C++11 standard

Let’s get started

Functional programming is a declarative type of programming style. Its sole focus is on “what to solve” in contrast to an imperative style where the main focus is on “how to solve“. It uses expressions instead of statements.

Functional Programming Key Concepts

  • Functions as first class objects

  • Pure functions

Functional Programming Rules

  • Immutable variables: In functional programming, you can’t modify a variable after it’s been initialized. You just can’t. You can create new variables but you can’t modify existing variables.

  • No side effects: A side effect is a state change in something other than the function that’s currently executing. Modifying a variable defined outside the function, printing out to the console, raising an exception, and reading data from a file are all examples of side effects.

  • No state: A function may have local variables containing temporary state internally, but the function cannot reference any member variables of the class or object the function belongs to. State encourages mutability leading to side effects. Functional Programming doesn’t want you to do that.

These are a few key concepts, rules of FP. Even if you do not follow all of these rules all the time, you can still benefit from the FP ideas in your applications. Anyways, C++ was never meant to be a strict or pure functional programming language. To be honest, functional programming is not the right tool for every problem(Yeah! It’s my opinion. It might change in future. Opinions do change with experience!). For now, let’s learn what problems FP is good at solving.

Functions as first class objects

In the functional programming world, functions are first-class objects. Functions are treated like any other variable. For example, a function can be passed as an argument to other functions and can be assigned as a value to a variable.

i = 0 i = 7 j = 9 i = 0

about the book

Functional Programming in C++ helps you unleash the functional side of your brain, as you gain a powerful new perspective on C++ coding. You’ll discover dozens of examples, diagrams, and illustrations that break down the functional concepts you can apply in C++, including lazy evaluation, function objects and invokables, algebraic data types, and more. As you read, you’ll match FP techniques with practical scenarios where they offer the most benefit.

Enhancing cybersecurity measures.

Advantages
 

Simple

The restrictions that pure functions and immutability enforce foster simplicity. Like I mentioned previously, I distinctly mean simple and not easy. Rich Hickey elaborates this in his talk “Simple made easy”. When we talk about writing code, simple code is clear, precise, concise, and therefore easy to understand. Simple code is therefore not easy to write. Easy being “lying near” or more precisely the first implementation that comes to mind.

FP doesn’t guarantee that you write simple code, but pure functions and immutable variables provide a structure that helps with writing simple code. Side-effects and mutations create a mess in our software because we need to handle edge and error cases. In FP we isolate our data and pure functions (or calculations) from the side effects and mutations. This means we don’t need to deal with error handling and null checks, etc. in our actual algorithms. Because of that our algorithms are stripped down to the core of what they are about. Further, since we adhere to the immutability principle, we use declarative code to implement our algorithms. Declarative code describes its intent and is therefore also simple.
 

Testable

Have you ever spent hours just trying to get a mock to work? I have and it sucks. It’s frustrating because it feels like you’re wasting time that you could have spent implementing features. I’ve been on a project where colleagues skipped writing tests because mocking was too much of a hassle. Guess what, pure functions don’t need any mocks to be tested. This means that the entire core of your application can be tested without mocks in FP. What’s even better though, you can mathematically prove the correctness of pure functions. Unit tests without mocks are easier and faster (less code) to write and give high confidence in the correctness of your implementation
.

Reusable

Three properties of FP make its functions very reusable.

  • First Class Functions, meaning you can pass functions as parameters to a function and also return functions, allows functions to be reused in various scenarios.

The next two are more advanced concepts that I haven’t explained yet. I will do that in a future blog post

  • Composition. If you think about pure functions for a moment, you realise that you can’t use a function in the body of another function (unless passed as a parameter), because then the function would have a dependency and would therefore be impure. This is where composition comes in. With composition, you can chain functions and thereby combine them.

  • Currying and partial application. When we curry a function we take a function with multiple parameters and turn it into several functions with one of the parameters of the original function each. I can then use partial application to supply any number of those parameters and get a function that accepts the next parameter. This is similar to method overloading in other languages. This technique allows me to reuse the logic of a function in different contexts that provide different types of input parameters.

Scalable

Gone are the days where our CPU cores got (much) faster. Modern CPUs are made up of lots of cores. If you want to make use of those, your software needs to implement some way to deal with threads and concurrency. As I explained previously pure functions and immutable data make a program thread-safe. Hence your software becomes scalable.
 

Disadvantages
 

Memory usage and performance

Immutable variables come with the trade-off that as you’re not changing the existing variable you create a new one. This means double the memory usage. If we are talking about large, nested data structures, this can also impact performance because of the overhead of copying the data over instead of just changing the existing one. Functional languages usually have ways to make sure you don’t have this trade-off by using things like tail call optimisation, lazy evaluation, and smart linking instead of copying the actual data. However, multi-paradigm- or OOP languages might not have implemented these optimisations.

Fewer frameworks and tools
 

As functional programming languages are used less than other languages, more popular languages like Java or JavaScript have a bigger community and hence more frameworks, tools, and reusable packages. This can become a major issue if components of your architecture don’t support integration with the functional language of your choice. One would think that in the age of cloud and containers this wouldn’t be a problem anymore. However, different cloud services, databases, and other tools still have a lot of restrictions when it comes to language support.
 

Fewer users/experts

If a company chooses to embrace a functional programming language, one crucial thing is to consider the availability of experts in that language. The language might be the perfect fit for the use case but if you can’t find the experts to support this over time, you may have to source it from a specialised vendor that is likely going to charge a premium due to the scarcity of said language.

Other considerations
 

The famous French philosopher Claude Lévi-Strauss would say of certain tools:

“Is it good to think with?”.

Functional Programming is an approach to dissect a problem in a certain way. Eric Normand describes this as actions, calculations, and data in his book Grokking Simplicity. Actions are interactions with the outside world. Actions are I/O operations or any operations that are impure. Calculations are pure functions that operate on (immutable) data.

Other paradigms take a different approach. In OOP we dissect problems differently. We separate data and operations that work on that data into classes that represent both. We also try to shape these according to what we find IRL and define the relationship between them.
 

The question is which approach do you find “good to think with?” I think the response here can differ from person to person and even for one person from problem to problem.

I am a big fan of functional programming and for me, it’s the most natural “tool to think with” that comes with some great advantages. However, it’s not suitable all the time. I hope that functional programming will continue to become more popular and therefore an even better alternative for businesses.

C++ is widely regarded as one of the most powerful programming languages available today. Its combination of features, including performance, flexibility, control over hardware resources, and extensive libraries, makes it a popular choice for a wide range of applications.

Performance is one of the key strengths of C++. Unlike interpreted languages like Python or Java, which rely on virtual machines or interpreters, C++ code is compiled directly into machine code, resulting in highly efficient and fast-running programs. This makes C++ an ideal choice for applications where speed is critical, such as real-time systems, game development, and high-frequency trading platforms.

C++ provides developers with a high degree of control over hardware resources, allowing them to optimize their code for specific architectures and platforms. This level of control is particularly important in embedded systems programming, where resource constraints are common, and performance is paramount. By directly accessing hardware features and manipulating memory at a low level, developers can squeeze every last drop of performance out of their code.

Another factor contributing to the power of C++ is its support for both procedural and object-oriented programming paradigms. Procedural programming allows developers to write code in a structured, modular manner using functions and procedures, while object-oriented programming (OOP) enables the creation of reusable and extensible software components through concepts like classes, objects, inheritance, and polymorphism.

Classes are fundamental building blocks in C++, allowing developers to encapsulate data and behavior into objects. For example, in a game development scenario, a "Player" class may encapsulate attributes like player health, position, and methods like move() and attack(). Objects are instances of classes, each with their own state (data) and behavior (methods).

Inheritance allows classes to inherit properties and behavior from other classes, promoting code reuse and enabling hierarchical organization of classes. For instance, a "Monster" class might inherit from a more general "Creature" class, inheriting common attributes and methods while adding its own unique functionality.

Polymorphism enables objects of different classes to be treated as objects of a common superclass, simplifying code and promoting flexibility. For example, a "Shape" superclass may have subclasses like "Circle" and "Rectangle". Code that operates on shapes can treat circles and rectangles uniformly, without needing to know their specific types.

Encapsulation refers to the bundling of data and methods that operate on that data within a single unit, typically a class. This helps to hide the internal implementation details of a class from the outside world, promoting modularity, maintainability, and code reliability.

C++ also supports generic programming through templates, which allow developers to write code that operates on generic types. Templates enable the creation of functions and classes that can work with any data type, providing a high degree of flexibility and code reuse. For example, a generic sorting function can be implemented using templates to sort arrays of any data type.

Memory management in C++ is another area where its power shines through. Unlike managed languages like Java or C#, where memory allocation and deallocation are handled automatically by the runtime environment, C++ gives developers direct control over memory management. This allows for fine-grained optimization of memory usage and efficient resource utilization. However, with great power comes great responsibility, as manual memory management in C++ also introduces the risk of memory leaks and segmentation faults if not handled properly.

Exception handling is another powerful feature of C++, allowing developers to handle runtime errors and abnormal conditions gracefully. Exceptions provide a mechanism for transferring control from the point of error detection to a block of code designed to handle the error, improving program robustness and reliability. By separating error-handling logic from the main application code, developers can write cleaner and more maintainable code.

The Standard Template Library (STL) is a core part of C++ that provides a rich collection of generic data structures and algorithms. It includes containers like vectors, lists, and maps, as well as algorithms for searching, sorting, and manipulating these containers. The STL promotes code reuse and standardization, making C++ development more efficient and productive.

C++ is also known for its extensive ecosystem of third-party libraries and frameworks, which further extends its capabilities. Libraries like Boost provide additional functionality for tasks such as multithreading, networking, and cryptography, while frameworks like Qt offer tools for building cross-platform GUI applications. These libraries and frameworks leverage the power and flexibility of C++ to provide developers with powerful tools for building complex and feature-rich software systems.

Despite its many strengths, C++ is not without its challenges. Its complexity and steep learning curve can be daunting for beginners, and its low-level features require a deep understanding of computer architecture and system programming concepts. Additionally, manual memory management and the absence of built-in garbage collection make C++ more prone to memory-related bugs and vulnerabilities if not used carefully.

In conclusion, C++ is undeniably a powerful programming language with a rich set of features and capabilities. Its performance, flexibility, control over hardware resources, and extensive libraries make it a popular choice for a wide range of applications, from system programming to game development to embedded systems. While mastering C++ may require time and effort, the rewards are well worth it for developers looking to build high-performance, efficient, and reliable software systems.

  • Array elements can be inserted and printed in C++ and C programming languages. In C++, use the 'push_back' command to add elements to the array. In C programming language, use the 'insert' command to insert array elements and 'printf' to print out the array.

  • Declaring an array in C or C++ is a simple process. In the most basic sense, an array is a collection of related data items that a single variable name can reference. In C and C++, the array is declared using the square bracket ([ ]) notation after the data type.

  • Arrays can be initialized in C and C++ using one of two methods. The first is by assigning each element a separate value. This can be done using a for loop or manually. The second method uses the array initialization list syntax, which uses curly brackets ({}).

  • In C++ and C programming, an array can be accessed using the index of the element that is to be accessed. The syntax for accessing an array element in C++ and C follows the format: [index]. For instance, if we have an array named arr and want to access the third element of that array, we would use the syntax arr3. Similarly, if we have an array named myarr and want to access the fifth element of that array, we would use the syntax myarr5. It's important to note that array indexes start from 0, so if we want to access the first element of an array, we would use the syntax [0].

    Company

  • In C and C++, a multi-dimensional array is an array of arrays. It is composed of two or more dimensions, with each dimension being indexed. Multi-dimensional arrays are usually used to store information in a structured way, allowing for easy access and manipulation of data elements.

 Protecting against malicious attacks.

Optimizing Tasks: Priority Scheduling Program in C

In the realm of computing, managing tasks effectively is paramount. This is where Priority Scheduling steps in as a powerful technique. 

 

At its core, Priority Scheduling program in C involves arranging tasks based on their relative priorities, ensuring that higher-priority tasks get executed before lower-priority ones. 

 

Imagine juggling multiple tasks in your daily life; you’d naturally tackle the more urgent matters first. Similarly, a Priority Scheduling program in C allows a computer to prioritize tasks intelligently.

Testing defenses against potential threats.

Binary Operators in C Programming

Application of a Binary Operator

The practical utilization of binary operators spans across numerous aspects of programming and beyond. Imagine a website’s login system, where the equality operator (==) matches the user’s input password with the stored one. In graphics processing, the bitwise shift operators (<< and >>) aid in swiftly moving pixels to generate animations or apply filters. In data encryption, the XOR operator (^) is pivotal in securing information by transforming it into a scrambled form. 

 

Promoting trust and confidence in digital systems."

Increment and Decrement Operators in C

Prefix and Postfix Decrement Operators

Prefix and postfix decrement operators are similar to their increment counterparts but perform the opposite operation. They are used to decrease the value of a variable by one in C programming.

With the prefix decrement operator (–num), the variable is decremented first, and then its updated value is used in the expression. For instance, if ‘num’ is 5 and we use ‘–num’, it becomes 4 immediately, and the expression using ‘num’ will utilize this updated value.

In contrast, with the postfix decrement operator (num–), the current value of the variable is used in the expression first, then decremented. So, if ‘num’ is 5 and we use ‘num–‘, the expression will use 5, and after the expression is evaluated, ‘num’ will be decremented to 4.

bottom of page