# Irenic language comparisons: Ada and Rust, AoC overall

**URL:** <https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275>\
**Category:** General\
**Created:** [October 1, 2024, 11:49am UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275 "2024-10-01T11:49:27Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![cantanima](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/cantanima/32/121_2.png) [@cantanima](https://forum.ada-lang.io/u/cantanima)\
**Post date:** [October 1, 2024, 11:49am UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/1 "2024-10-01T11:49:27Z")

</div>

Building on @JeremyGrosser’s invitation and an earlier, problem-specific comparison I made here, I’ve written up [a more general comparison](https://github.com/johnperry-math/AoC2023/blob/master/More_Detailed_Comparison.md)\*\*\* that compares four or five common constructions, depending on how you count: file iteration and exception handling, modularity and generics, enumerations, filtered and enumerated iteration. If that sort of thing interests you and you found the previous discussion useful, feel free to read it, and I’d be happy to receive any corrections or comments.

Otherwise I make no claim to suitability or usefulness. The writeup is longer and wordier than I expected and wanted, even after a significant pruning. Still, I learned a few things in the making of it, including a few surprises.

\*\*\*ironically filenamed `More_Detailed_Comparison` but I don’t think it is in fact detailed

---

<div class="post-metadata">

**Author:** ![Lucretia](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/lucretia/32/17_2.png) [@Lucretia](https://forum.ada-lang.io/u/Lucretia)\
**Post date:** [October 1, 2024, 1:58pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/2 "2024-10-01T13:58:50Z")

</div>

Er…what??

is there a link missing or something?

---

<div class="post-metadata">

**Author:** ![cantanima](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/cantanima/32/121_2.png) [@cantanima](https://forum.ada-lang.io/u/cantanima)\
**Post date:** [October 1, 2024, 2:13pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/3 "2024-10-01T14:13:01Z")

</div>

Whoops. Don’t know how I missed that. Fixed, & thanks.

---

<div class="post-metadata">

**Author:** ![Lucretia](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/lucretia/32/17_2.png) [@Lucretia](https://forum.ada-lang.io/u/Lucretia)\
**Post date:** [October 1, 2024, 2:26pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/4 "2024-10-01T14:26:22Z")

</div>

Eek (the cat), that is long.

---

<div class="post-metadata">

**Author:** ![jere](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jere/32/87_2.png) [@jere](https://forum.ada-lang.io/u/jere)\
**Post date:** [October 1, 2024, 2:33pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/5 "2024-10-01T14:33:59Z")

</div>

Looks pretty interesting!

One correction: Expression functions were added in Ada2012 (The original release, before the 2015 update to 2012). (See side note at bottom of the post)

Also a question, you list Spark/Ada not having optional or result values, but I would have expected at least an “available with library” since it really just requires a variant record in Ada/Spark to implement? I get that it isn’t a 1st class type like it is in Rust. Maybe some clarification?

On the table or run time results: it might be good to at least list the switches you used for both Ada and Rust. In particular for Ada they make a huge difference because they can affect things like container performance which is usually a bottleneck in large data manipulation.

SIDE NOTE: You can generally figure out when a feature was added to the language by looking at the “slash numbers” in the RM. I know it isn’t available at the ARG website right now, but I keep a local copy (I have trouble reading the version stored here at [ada-lang.io](http://ada-lang.io)). The ending /1 /2 /3 /4 /5 all have specific Ada revisions associated with them so you can scan a section and look for the earliest slash number to get an idea when something was added. In particular a quote from the RM:

> [@](#):
>
> Changes to the original 1995 version of the Ada Reference Manual can be identified by the version number following the paragraph number. **Paragraphs with a version number of /1 were changed by Technical Corrigendum 1 for Ada 95** or were editorial corrections at that time, while **paragraphs with a version number of /2 were changed by Amendment 1** or were more recent editorial corrections, and **paragraphs with a version number of /3 were changed by the 2012 edition** of the Reference Manual (including additional editorial corrections). **Paragraphs with a version number of /4 were changed by Technical Corrigendum 1 for Ada 2012** or were editorial corrections at that time. **Paragraphs with a version number of /5 were changed by the 2022 edition** of the Reference Manual (including additional editorial corrections). Paragraphs not so marked are unchanged since the original 1995 edition of the Ada Reference Manual, and have the same paragraph numbers as in that edition. In addition, some versions of this document include revision bars near the paragraph numbers. Where paragraphs are inserted, the paragraph numbers are of the form pp.nn, where pp is the number of the preceding paragraph, and nn is an insertion number. For instance, the first paragraph inserted after paragraph 8 is numbered 8.1, the second paragraph inserted is numbered 8.2, and so on. Deleted paragraphs are indicated by the text _This paragraph was deleted._ Deleted paragraphs include empty paragraphs that were numbered in the 1995 edition of the Ada Reference Manual.

" Amendment 1" for the /2 refers to Ada 2005

---

<div class="post-metadata">

**Author:** ![cantanima](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/cantanima/32/121_2.png) [@cantanima](https://forum.ada-lang.io/u/cantanima)\
**Post date:** [October 1, 2024, 6:19pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/6 "2024-10-01T18:19:17Z")

</div>

> [@Lucretia](#):
>
> Eek (the cat), that is long.

Yeah… 😩 I know, and I kept asking myself how to shorten it. I didn’t want to remove the “language overviews”, though. You should see what I took out. Probably would have been twice as long.

What do you mean by “the cat”?

> [@jere](#):
>
> Expression functions were added in Ada2012 (The original release, before the 2015 update to 2012). (See side note at bottom of the post)

Dang! I kenw that, too! Somehow I got the two mixed up.

> [@jere](#):
>
> Also a question, you list Spark/Ada not having optional or result values, but I would have expected at least an “available with library” since it really just requires a variant record in Ada/Spark to implement?

To be honest, I added that 📖 icon for “library” availability primarily for Rust, and didn’t think about Ada / Spark originally. I only added the link to @mosteo 's iterators crate this morning, shortly before committing!

So I could see a new icon for “things relatively easily implemented in the other language”. But I’m not sure. There’s a lot more to rust’s `Option` and `Result` types; I mean more how they are used in error and data handling, where Ada would use exceptions. In other words, they induce a certain approach, which I happen to mention later. And with that comes a wide range of methods associated with the type that, yes, you _could_ implement in Ada, but now you’re talking about a lot more work.

It might be better to place them both in a separate category, something like “idiomatic error handling with types”. Not sure I like that either, though. I’m very open to suggestions.

> [@jere](#):
>
> SIDE NOTE: You can generally figure out when a feature was added to the language by looking at the “slash numbers” in the RM.

I always wondered what that was about. Thanks! 😁

---

<div class="post-metadata">

**Author:** ![cantanima](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/cantanima/32/121_2.png) [@cantanima](https://forum.ada-lang.io/u/cantanima)\
**Post date:** [October 1, 2024, 6:26pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/7 "2024-10-01T18:26:43Z")

</div>

@jere I forgot to reply to this:

> [@jere](#):
>
> On the table or run time results: it might be good to at least list the switches you used for both Ada and Rust. In particular for Ada they make a huge difference because they can affect things like container performance which is usually a bottleneck in large data manipulation.

I thought I had mentioned how those were built; I know at one point I was ⚠ warning ⚠ that time comparisons weren’t that great because of differences in compilers, and I couldn’t control what the compilers did, and that did start me on an investigation of activating/deactivating switches, which is how I discovered that the Rust code for Day 23 was exiting with an error message whenever I enabled overflow checks in `--release` mode.

I hope you don’t mind that tangent. To answer your question: Unless specified otherwise,

- “development” means whatever the standard `alire` or `cargo` switches are
- “release” means `alire build --release` and `cargo build --release`

I think I would prefer to say just that, but if you prefer I’ll look at the configuration files that `alire` and `cargo` create and list those details.

---

<div class="post-metadata">

**Author:** ![Lucretia](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/lucretia/32/17_2.png) [@Lucretia](https://forum.ada-lang.io/u/Lucretia)\
**Post date:** [October 1, 2024, 6:38pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/8 "2024-10-01T18:38:10Z")

</div>

> [@cantanima](#):
>
> What do you mean by “the cat”?

The stupid reply limit, so added that in brackets. Do a search for eek the cat.

---

<div class="post-metadata">

**Author:** ![jere](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jere/32/87_2.png) [@jere](https://forum.ada-lang.io/u/jere)\
**Post date:** [October 1, 2024, 7:07pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/9 "2024-10-01T19:07:02Z")

</div>

> [@cantanima](#):
>
> What do you mean by “the cat”?

It’s meant to be humorous (and to fill space in the reply).  
For reference: [Eek! The Cat - Wikipedia](https://en.wikipedia.org/wiki/Eek!_The_Cat)

> [@cantanima](#):
>
> There’s a lot more to rust’s `Option` and `Result` types; I mean more how they are used in error and data handling, where Ada would use exceptions. In other words, they induce a certain approach, which I happen to mention later. And with that comes a wide range of methods associated with the type that, yes, you _could_ implement in Ada, but now you’re talking about a lot more work.

Definitely. You had specifically sectioning out pattern matching so I figured you were lumping the other stuff in with that based on the examples. Maybe just a blurb that it can be implemented via variant records or something. Either way, not a complaint. I enjoyed reading through it.

> [@cantanima](#):
>
> I hope you don’t mind that tangent. To answer your question: Unless specified otherwise,
> 
> - “development” means whatever the standard `alire` or `cargo` switches are
> - “release” means `alire build --release` and `cargo build --release`
> 
> I think I would prefer to say just that, but if you prefer I’ll look at the configuration files that `alire` and `cargo` create and list those details.

Something to consider here. Since you are doing a performance assessment and Alire’s defaults are subject to change, it may be a good idea to list out the switches somewhere for those less familiar with alire and to also cover you in case Alire decides to add/remove switches later in life. Also, I don’t know if Alire turns off tampering checks and such in release mode off hand?

---

<div class="post-metadata">

**Author:** ![zertovitch](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/zertovitch/32/90_2.png) [@zertovitch](https://forum.ada-lang.io/u/zertovitch)\
**Post date:** [October 1, 2024, 7:11pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/10 "2024-10-01T19:11:44Z")

</div>

Very interesting!  
In the grid, what kind of “macro programming” can’t you do in Ada ?  
I would add a row about OOP and inheritance (the Rust doc says it can’t do that).

---

<div class="post-metadata">

**Author:** ![cantanima](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/cantanima/32/121_2.png) [@cantanima](https://forum.ada-lang.io/u/cantanima)\
**Post date:** [October 1, 2024, 7:23pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/11 "2024-10-01T19:23:10Z")

</div>

Can you do _any_ kind of macro programming in Ada? I thought Ada was one of those “we don’t need no stinkin’ macros” languages, which I sympathize with sometimes, as in, when I’m trying to make sense of some stinkin’ Rust macro.

I don’t mean generics, by the way, as I mentioned those elsewhere. I mean code that lets you manipulate the abstract syntax tree at compile time, modifying the code then, usually with the aim of saving a bunch of boilerplate, but sometimes making it impossible even for the IDE to grok the flow.

---

<div class="post-metadata">

**Author:** ![Lucretia](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/lucretia/32/17_2.png) [@Lucretia](https://forum.ada-lang.io/u/Lucretia)\
**Post date:** [October 1, 2024, 7:34pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/12 "2024-10-01T19:34:20Z")

</div>

[Nope](https://github.com/Ada-Rapporteur-Group/User-Community-Input/issues/104)

---

<div class="post-metadata">

**Author:** ![zertovitch](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/zertovitch/32/90_2.png) [@zertovitch](https://forum.ada-lang.io/u/zertovitch)\
**Post date:** [October 1, 2024, 7:58pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/13 "2024-10-01T19:58:00Z")

</div>

Probably we think to different kind of macros.  
Of course Ada’s generics are not a simple text substitution, but (unless you have shared generics) it actually works like that in the end. The compiler will check on the way that you don’t put a type in the place of a function, and so on, so you can check the generic unit before even instantiating it and be confident that most instantiations will work.  
The RM says: “Generic units can be used to perform the role that macros sometimes play in other languages”

---

<div class="post-metadata">

**Author:** ![Lucretia](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/lucretia/32/17_2.png) [@Lucretia](https://forum.ada-lang.io/u/Lucretia)\
**Post date:** [October 1, 2024, 8:30pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/14 "2024-10-01T20:30:55Z")

</div>

Yeah, the [macros](https://en.wikipedia.org/wiki/Hygienic_macro) above are a meta-programming construct, which I think Ada should have.

---

<div class="post-metadata">

**Author:** ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)\
**Post date:** [October 1, 2024, 10:00pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/15 "2024-10-01T22:00:41Z")

</div>

> [@jere](#):
>
> Also a question, you list Spark/Ada not having optional or result values, but I would have expected at least an “available with library” since it really just requires a variant record in Ada/Spark to implement? I get that it isn’t a 1st class type like it is in Rust. Maybe some clarification?

> [@cantanima](#):
>
> So I could see a new icon for “things relatively easily implemented in the other language”. But I’m not sure. There’s a lot more to rust’s `Option` and `Result` types; I mean more how they are used in error and data handling, where Ada would use exceptions. In other words, they induce a certain approach, which I happen to mention later. And with that comes a wide range of methods associated with the type that, yes, you _could_ implement in Ada, but now you’re talking about a lot more work.

There are three ways that you can do something akin to optional types in Ada:

1. An instance of `Ada.Containers.Indefinite_Holders`; [Ada2012]
2. Variant records; [Ada83]
3. Arrays, unconstrained; [Ada83]

This last one is really quire trivial:

```ada
Subtype Optional_Index is Boolean range True..True;
Type Optional is array (Optional Index range <>) of ITEM_TYPE;
None : Optional Constant := ( True..False => <> );

-- The Item returned by EXAMPLE is an array of length 0 or 1.
Function Example return Optional;

```

The only time you can’t use #3 is when you have discriminants (because discriminant → unknown-size).

---

<div class="post-metadata">

**Author:** ![jere](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jere/32/87_2.png) [@jere](https://forum.ada-lang.io/u/jere)\
**Post date:** [October 1, 2024, 10:08pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/16 "2024-10-01T22:08:44Z")

</div>

You also cannot use #3 if you are storing results in an array since Optional is an unconstrained type.

---

<div class="post-metadata">

**Author:** ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)\
**Post date:** [October 1, 2024, 10:17pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/17 "2024-10-01T22:17:29Z")

</div>

?  
It’s perfectly legitimate to say:

```ada
   Constant_Value : Constant Optional := Example;
-- OR, BETTER:
   Renamed_Value : Optional renames Example;

```

Or do you mean `X : Array (positive range <>) of Optional:= WHATEVER`?

If you really need that sort of construct, consider what you’re _really_ doing, and if you need it, use `Ada.Containers,Indefinite_Vectors` instantiated w/ Option.

---

<div class="post-metadata">

**Author:** ![jere](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jere/32/87_2.png) [@jere](https://forum.ada-lang.io/u/jere)\
**Post date:** [October 1, 2024, 11:22pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/18 "2024-10-01T23:22:16Z")

</div>

> [@OneWingedShark](#):
>
> If you really need that sort of construct, consider what you’re _really_ doing, and if you need it, use `Ada.Containers,Indefinite_Vectors` instantiated w/ Option.

Generally the place where I really consider using optional is in environments where I don’t always have heap allocation or exceptions (small embedded platforms).

I do consider what I am really doing. I think hard about it.

I feel like programming in Ada is a lot about learning to represent your design in code in a way that makes the most sense. Things that lean towards optional results really do lean more towards variant records for me. Sure using an array works in some situations but it feels like a pretty unintuitive way to implement it for me if someone else is reading your code (I’m not saying you are wrong for suggesting it, just talking about my own preference). I much prefer the variant record approach, but I think each of us can pick what we like best out of the options.

---

<div class="post-metadata">

**Author:** ![evanescente-ondine](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/evanescente-ondine/32/451_2.png) [@evanescente-ondine](https://forum.ada-lang.io/u/evanescente-ondine)\
**Post date:** [October 2, 2024, 12:25am UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/19 "2024-10-02T00:25:49Z")

</div>

Technically GNAT provides metaprogramming already, several compilers used to, I don’t know if it is still the case.  
There are several ways, some innocent (conditional branches being hardcoded and the alternatives not compiled at all when depending on a **static** boolean expression, switching bodies depending on the machine or compiler switches) or not (fully on metaprogramming).  
The latter is an old way of thinking, like worrying about your variable going in memory or registers. It’s a compiler/automated tools’s job to find and discard conditionally dead code.  
The rest is good design and profiting from these capacities of separate compilation no other language has, to their fullest extent

---

<div class="post-metadata">

**Author:** ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)\
**Post date:** [October 2, 2024, 9:06pm UTC](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275/20 "2024-10-02T21:06:09Z")

</div>

> [@jere](#):
>
> Sure using an array works in some situations but it feels like a pretty unintuitive way to implement it for me if someone else is reading your code (I’m not saying you are wrong for suggesting it, just talking about my own preference).

Interesting.  
Why is that?  
I mean, returning a variable-length array is idiomatic Ada. And there’s nothing too special about an array-length 0… so, having a variable-length array with an index which imposes a maximum of `1` seems the natural way of implementing much of what you’d want to use `Optional` for… **plus** , unconstrained-arrays offers a way to naturally express the notion of operating on sets/collections of that element-type.

> [@jere](#):
>
> I much prefer the variant record approach, but I think each of us can pick what we like best out of the options.

Variant records map well to the domains of HW-interface and protocol[-packet] definition. They also can be used to interface and “hoist” the ‘parameters’ of the type. e.g.

```ada
Type Message(Length : Natural) is record
   Text : String(1..Length):= (others => ' ');
end record;

Type Style in (Plain, Extra);

Type Packet(Length: Positive; Packet_Type : Style) is record;
   Text : Message(Length);
   case Packet_Type is
      when Extra => Data : Integer;
      when Plain => Null;
   end case;
end record;

```

[Next page](https://forum.ada-lang.io/t/irenic-language-comparisons-ada-and-rust-aoc-overall/1275.md?page=2)
