ADA#

Introduction#

A few weeks ago, a colleague mentioned Ada to me, a language I knew vaguely for its speed and its applications in the aerospace industry, especially in aircraft development. With this minimal knowledge, I dove into the world of Ada.

My curiosity grew as I noticed the scarcity of informal resources for learning the language, like videos or basic tutorials. I found incomplete YouTube playlists and blogs that only covered basic topics like loops. Surprisingly, I couldn’t even find courses on popular platforms like Udemy or Coursera. This might discourage anyone, but in my case, I took it as a challenge and decided to explore this language that’s so outside the mainstream.

First Steps#

As is usually the case when learning a new language, the first thing I did was consult the official documentation. With a reference manual and the guide from AdaCore in hand, I started taking my first steps.

HELLO WORLD#

My first impression when writing a hello world was that Ada had a somewhat rustic style, similar to Pascal, with its procedures, begin, and end. I also noticed an indentation format similar to Python. I didn’t find here the complexity that sometimes appears in other languages, like Java, when writing a simple program. This gave me confidence to continue.

Functions#

With a bit of confidence, I decided to move quickly and dive into the topic of functions. Here, Ada also reminded me of Pascal, especially with the distinction between procedure (which returns nothing) and function (which does return a value). The difference is that, in Ada, the return type is placed at the end of the function, in contrast to languages like C, where it appears at the beginning. I implemented some simple functions for basic mathematical operations, without too many surprises in this regard.

Recursion#

Although recursion is not usually popular among programmers, I have always found something aesthetically interesting about its use, and it’s a topic I often test when learning a new language.

Recursion in Ada presented no issues, until I tried calculating high numbers in the Fibonacci sequence. For small numbers, everything worked well; however, when reaching higher values, I encountered an error due to integer size limitations. Looking for a solution, I discovered the Big Numbers package, but when I tried compiling it, I encountered an error indicating that the package didn’t exist. This led me to explore Alire, Ada’s package manager, and while it didn’t solve my problem at that moment, it was my first introduction to this tool.

Alire#

In my repository, there’s a branch called “Alire,” though I haven’t delved deeply into using this package manager yet. Here are my first impressions of Alire.

To begin with, Alire is a package manager for Ada. If you have experience with Rust, you’ll quickly notice that Alire is comparable to Cargo, though with some differences that make it interesting. However, the Alire community is relatively small, which is reflected in the quantity and variety of available packages. When browsing the list of crates on its website, it feels like many packages are overly specific, and the lack of a large and diverse community limits the options and breadth of applications.

When compared to crates.io from Cargo, the difference is clear. Cargo’s website is much more user-friendly, with an advanced search and tags that make it easier to find packages of interest without relying so much on exact names or descriptions. In Alire, the search can sometimes be less efficient, and navigation between categories isn’t as intuitive; although, interestingly, using ctrl + f and tags manually can be more practical.

Additionally, I’ve experienced some inconveniences when compiling with Alire. While I appreciate the programming errors and important warnings, the style warnings can sometimes feel excessive, especially in personal projects where following a specific format isn’t as relevant. I understand that these warnings can be useful for learning the language’s conventions, but in my case, I prefer to focus on functionality over style. There might be a way to disable these style warnings, but I haven’t explored it fully yet.

In summary, I believe Alire has potential, but the lack of community limits the development of a broader and more robust ecosystem. With a more active community, these limitations would likely be gradually overcome.

Semaphores#

This is the previously mentioned project called Alire, although it doesn’t actually leverage this package manager. My goal in this code was to explore both concurrency and parallelism in Ada, which, from what I’ve researched, seems to be one of the language’s strong points. Getting everything to work correctly wasn’t easy; as I mentioned earlier, the style warnings from Alire, though useful in other contexts, didn’t help in identifying actual functional issues. However, with persistence, I managed to build a functional simulation of a traffic system with traffic lights and vehicles. Here are some project highlights:

  • I implemented tasks for the traffic lights and vehicles so that each one could monitor and coordinate with the others’ state.
  • To ensure vehicles could cross the intersection without collisions, I used a protected type called Intersection. Protected types in Ada allow controlled concurrent access to shared resources, which is essential in systems where multiple processes might access the same resource.
  • To manage state changes in the traffic light and receive vehicle requests, I used entries in the TrafficLight task like Change_To_Green and Change_To_Red. Using the select statement, I was able to make the traffic light accept these entry calls based on its current state.

Motion Detector#

In this project, I ultimately decided to set Alire aside for another time and treat it as a future learning opportunity. The idea to implement a motion detector arose for two reasons: first, upon exploring Alire’s crates page, I noticed there wasn’t anything comparable to OpenCV; second, I remembered a previous project where I integrated C code into Rust using Cargo. While this introduced unsafe code somewhat contrary to Rust’s philosophy, it was a good opportunity to experiment. This time, I wanted to try something new and explore Ada’s possibilities in combination with OpenCV.

My approach was to identify which OpenCV functions were necessary to implement a motion detector in C++ and then develop a wrapper that could integrate with Ada. This wrapper manages the creation of the detector, frame capture, and motion processing operations. Through pragma Import, I exposed the C++ wrapper functions to Ada, allowing me to work with these OpenCV functionalities directly from Ada code. This experience helped me understand how to handle interoperability between Ada and C++, especially in more complex projects.

During development, learning to coordinate concurrent tasks was also key. The Save_Motion task runs in parallel, saving frames with detected motion without interfering with real-time capture. Ada facilitated this structure through the use of tasks, and I learned a lot about managing real-time systems. Synchronizing shared resources was another challenge that Ada helped simplify, especially in coordinating safe access to OpenCV resources.