1. 4

    Trying to learn how to be more clean and organized. I find it hard to get rid of things which aren’t trash. I don’t often buy myself stuff, I have trouble dealing with the generous nature of some of my family members. e.g. I have 6 backpacks I’ve collected over the years.

    1. 2

      I sympathize. My technique: Find a good cause to give away things to which will get them to people who need them; something more charitable than a for-profit second-hand store like Goodwill. Then have a Pile of Stuff, such as the 4-5 backpacks you don’t use. Then once a year you go through the Pile, look at each thing, and say either “I haven’t used this in a year, so I’m not going to need it” and give it away, or “I plan to use this for X in the next year” and keep it.

      That said, I’m still bad at this, and there’s endless “decluttering” books and such out there.

      1. 1

        a for-profit second-hand store like Goodwill

        Do you have a source for that? To my knowledge Goodwill operates as a 501c3 at both the parent organization level, as well as the retail stores themselves.

        1. 1

          Double-checked and shit you’re right. My memory was faulty. Thank you!

          1. 1

            There have been stories that have come up questioning if Goodwill should be a 501c3.

            1. 1

              Maybe it’s a relatively new development. I’ll have to do some research.

    1. 10

      It’s not about modernity, but ability to fix things in a timeframe shorter than decades. C has fully embraced ossification as a symbol of stability and compatibility, and C++ has made the C community prejudiced against any new language features.

      In C, there’s no hope to get even smallest most broken things fixed in a reasonable time. 5 years or longer to get something into the standard (if it gets in at all), several years until it’s implemented, then a few more years before laggard Linux distros update their compilers, then projects will wait a couple more years just in case someone still has an old compiler. If you support MSVC that’s an extra 10 years of waiting until Microsoft puts it on their roadmap, and writes a sub-par implementation. And then you will still run into projects that insist on staying on C89 until the end of time.

      In Rust, for small warts, the time between “this is stupid, we should fix it” and having it fixed in production is 3 months, maybe a year.

      1. 10

        There came a time when I got tired of running as fast as I could just to stay in place. And it seems to me that with modern languages du jour, that’s all you are doing—running as fast as you can just to stay in place.

        1. 3

          Depends what you use — Node.js has a senseless policy of making semver-major ( = breaking) releases every 3 months, which ripples through the JS ecosystem. Swift went through a lot of churn too.

          OTOH Rust has stabilized over 6 years ago, and kept very stable. I have a project from 2016 that uses Rust + JS + C. Rust builds perfectly fine, unchanged, with the latest compiler. JS doesn’t build at all (to the absurd level that the oldest Node version compatible with my OS is too new to run newest versions of packages compatible with my JS). I’ve also had to fix the C build a few times. C may be dead as a language, but clang/gcc do change and occasionally break stuff. C also isn’t well-isolated from the OS, so it keeps tripping up on changes to headers and system dependencies. In this regard Rust is more stable and maintenance free than C.

          1. 2

            Not sure where you are getting your information about Node.js releases. New LTS (even-numbered) major versions are released every year, with minor non-breaking version updates more frequently.

            1. 1

              Sorry, every 6 months: v16 2021-04-20, v17 2021-10-19, v18 2022-04-19. This isn’t merely a numbering scheme, they really reflect semver-major breaking changes. I’d prefer Node not to be on v18.x.x, but on v1.18.x, maybe v2.9.x. LTS doesn’t fix Node’s churn problem. It’s merely a time bomb, because you have to upgrade to a newer LTS and face the breakage eventually.

              I much prefer Rust’s approach of staying on 1.x.x forever, because I can upgrade the compiler every month, keep access to latest-greatest features, and add newly-released dependencies, but still be able to build a 6-year-old project with 6-year-old dependencies and upgrade it on my own schedule.

            2. 1

              C may be dead as a language

              It’s not dead as much as usually not used as the primary language for applications. It has a bunch of niches in which it’s used as a low level glue, and there’s quite a few embedded developers who use it.

              on changes to headers and system dependencies

              Programs which break due to header changes are often the result of people not properly including all of the things that they need. This can be a very hard problem to solve because of how header files can be implicitly included, though there are some tools like IWYU which can help mitigate the problem.

              1. 3

                I mean dead in terms of future evolution. TFA shows that even such a basic thing like parsing a number has a poor API that could have been fixed at any point in the last 40 years, but wasn’t. Users C of are so used to dealing with such papercuts, that often there’s no will to improve anything, so these problems will never be fixed.

                As for headers, I mean things like Linux distros changing headers in /usr/include. I don’t really have control over this in C — pkg-config or equivalent will give me whatever it has. In Rust/Cargo I have semver ranges and lockfiles that give me compatible dependencies.
                Same goes for compilers. There are known footguns like -Werror, but also subtler ones due to implementation changes. For example, apple-clang started “validating” header include paths for whatever SDK policy they had. Using GCC instead isn’t easy or reliable either, because Apple keeps adding non-standard C to their headers, even stdio.h. OTOH Rust works as a reliable baseline, and isolates me from these issues.

            3. 2

              C++ for all its faults is a decent middle ground in this respect. It’s steadily adding good features, without breaking backward compatibility (except a few edge cases.)

          1. 29

            I don’t see this as a case for a modern language, as much as a problem with working with C.

            This has worked in Ada since its initial version (Ada83), throws Constraint_Error on out of range and bad input, and works similarly on floats Float'Value(S), and even custom enumerations with their names with Enum_Type'Value(S).

            X : Integer := Integer'Value (S);
            

            Strings are also not null terminated, but there’s Interfaces.C.Strings if you need to convert to C-style to work with an imported function.

            1. 19

              I think here “modern” means “newer than 1970”.

              1. 14

                Lol in that case, C counts (created in 72).

                1. 4

                  EDIT: I think I wildly misinterpreted your point. I was considering “modern” by going off of this quote:

                  one of the several more modern languages that have sprung up in the systems programming space, at least for newly written code. I make no secret that I love Rust and Zig both, for many similar reasons. But I also find Nim to be impressive and have heard great things about Odin.

                2. 11

                  The C++11 versions of these functions also throw exceptions on out-of-range or parse-error conditions. This makes me a bit sad, because I normally disable exceptions in C++ - I wish the standards group would change their stance on subsetting and properly standardise the no-exceptions dialect.

                  1. 7

                    I haven’t tried them yet but C++2017 added from_chars and to_chars. They don’t throw exceptions or support localization.

                    1. 2

                      Zounds! I did not know of these.

                      1. 2

                        Thanks, that looks like exactly the API that I was looking for! Apart from the not supporting localization bit - it would be nice if they could take an optional std::locale. That said, another of my pet peeves with the C++ committee’s aversion to subsetting is that higher-level functionality such as locales are mandatory in all environments. You can sort-of get around this by defining precisely one locale (“C” or “POSIX”, the only one that POSIX requires to exist) but then you’re relying on your compiler to do a lot of tricky dead-code elimination.

                        1. 3

                          Not supporting a locale is a goal of those interfaces:

                          Unlike other formatting functions in C++ and C libraries, std::to_chars is locale-independent, non-allocating, and non-throwing. Only a small subset of formatting policies used by other libraries (such as std::sprintf) is provided. This is intended to allow the fastest possible implementation that is useful in common high-throughput contexts such as text-based interchange (JSON or XML).

                    2. 7

                      I’d consider Ada a modern language! At the very least, one of the earliest languages with modern sensibilities.

                      1. 8

                        I would consider never versions of Ada (especially Ada 2012) to be modern as well. My point was that the author was emphasizing much newer languages, and I was addressing that this has been solved in an older language for a long time.

                    1. 3

                      I am working on my talk for the Ada Devroom of FOSDEM 2022, “The Outsider’s Guide to Ada.” I’ve written in a lot of different languages for a long time before my year of Ada, so hopefully it will be a succinct and objective (no proselytizing) overview of the language for those unfamiliar with it. I’m trying to boil it down through its weird vocabulary, and show the good and the ugly parts.

                      1. 2

                        You just launched my favorite game of January : How much can I overbook a weekend with as much as possible Fosdem talks?

                        Your talk would be the first on the list ☺️

                      1. 2

                        If you include a language with a single implementation within your definition of portability, then this definitely is more portable than C.

                        Still, this goes without saying that we should simplify build-systems in general. A simple Makefile and a config.mk file for optional tweaks that don’t need to be done on 99% of systems suffices in most cases.

                        1. 25

                          Have you noticed that there no portable way to print “Hello World” in C?

                          There is a solid standard for source code that passively promises it could do it when built, but you can’t run this source code in a standard, portable way. I see people treat gcc on POSIX as this sort of standard, but it’s not. There are other compilers, other platforms, and even within gcc-flag-copying compilers on close-enough-to-POSIX systems it’s endless papercuts.

                          I had a simple Makefile with config.mk, and ended up in a situation where I couldn’t build my own project on my own machine. After days of debugging I think the simplest solution would be to recompile GCC from scratch with -mno-outline-atomics… but I just don’t want to deal with these things. In C everything is theoretically possible, but nothing is easy, nothing is reliable.

                          I’m completely unmoved by the theoretical possibility of porting my project to DEC Alpha or a DSP with 12-bit bytes, when I can’t even run it on macOS and Windows.

                          1. 1

                            I know about C’s inconsistencies and quirks, but it’s reasonable to just target a POSIX compliant system, which is a standard and clearly defines interfaces you can use to print “Hello World”.

                            I do not depend on the mercy of the Rust developers to support a certain platform,and when I check the Rust officially supported platforms I don’t see that many. Even Microsoft itself acknowledges that by offering WSL.

                            1. 15

                              Your position is odd. On one hand you seem to value support for all platforms, even ones that are too obscure too be in LLVM. But at the same time you say it’s reasonable to just drop the biggest desktop platform.

                              Porting Rust needs an LLVM back-end and libc, which is pretty much the same as porting Clang. You don’t need a permission from an ISO committee to do this. LLVM and Rust are open. In practice the list includes every modern platform people care to support. There’s also a GCC back-end in the works, so a few dead platforms will get support too.

                              1. 2

                                I think FRIGN is arguing that targeting POSIX does not mean dropping Windows, because WSL exists. I don’t agree, but it is an arguable position.

                                1. 7

                                  WSL is Linux. I would not call that targeting the Windows platform.

                                  1. 1

                                    Why not? WSL is part of Windows. What do you gain by targeting non-WSL Windows? (I think there is a gain, I am just curious what you think it is.) Is it that WSL is an additional install? (JVM is an additional install too, and frankly WSL is easier to install than JVM.) Is it support for versions older than Windows 10? Is it overhead, which I think is tiny?

                                    Would you stop targeting Windows if all of the following happens: 1) WSL becomes part of default install 2) all versions of Windows not supporting WSL become irrelevant 3) performance overhead improves enough to be immaterial? What else would you want?

                                    1. 13

                                      Windows can also run Web apps and Android applications, or even emulate an old Mac, but in a discussion of portability I think it’s important to make a distinction between getting software to run somehow vs being able to directly use the native vendor-recommended APIs of the platform.

                                      Is Visual Basic 6 portable and can target Linux? There is WINE after all, and it’s probably as easy to install as WSL.

                                      The WSL tangent feels like I’m saying “I can’t eat soup with a fork”, and you “You can! If you freeze it solid or if you spin the fork really really fast!”

                                      1. 2

                                        I also think depending on Wine instead of porting to Linux a defensible position.

                                      2. 4

                                        Why not? WSL is part of Windows. What do you gain by targeting non-WSL Windows?

                                        I worked at a place that wouldn’t allow WSL because the security team couldn’t install the network monitoring tool they used. Ultimately, it is an optional component and can be disabled.

                                        1. 3

                                          Why not? WSL is part of Windows. What do you gain by targeting non-WSL Windows?

                                          WSL is a brand name covering two things:

                                          • WSL1 uses picoprocesses in the NT kernel with a Linux system call compatibility layer (similar in concept to the *BSD Linux compat layers)
                                          • WSL2 just runs a Linux VM with Hyper-V.

                                          There is some integration with the host system, a WSL application in either version can access the host filesystem (with WSL1, there are filter drivers over NTFS that present POSIX semantics, with WSL2 it uses 9p over VMBus, both are slow). They can create pipes with Windows processes. But they can’t use any of the Win32 API surface. This means no GUI interaction, no linking with any Windows DLLs. For something like an image library (as in the article), providing a Linux .so is of no help to someone writing a Windows application. The most that they could do with it is write a Linux command-line tool that decoded / encoded an image over a pipe, and the run that win WSL, on the subset of Windows machines that have enabled WSL (unless it’s changed recently, neither WSL1 or 2 is enabled by default).

                                  2. 3

                                    I think it does boil down to the question whether targeting POSIX is reasonable or not. Many people, including myself and the author of this article, find it unreasonable. But I admit it is a defensible position.

                                2. 7

                                  That works unless it involves one of threading, Windows, or cross-compilation. All three works out of the box with Rust. C is more capable, but Rust is more convenient.

                                  1. 1

                                    That’s a fair point, but this only works because there is one single Rust implementation that is ported, and that’s what you depend on.

                                    I’m not arguing about the convenience.

                                  2. 4

                                    A simple Makefile and a config.mk file for optional tweaks that don’t need to be done on 99% of systems suffices in most cases.

                                    I’d argue the opposite, that cargo new and cargo build suffice in most cases, and you don’t need the capabilities of C most of the time unless you’re doing something weird, or something with hardware.

                                    1. 1

                                      But think about the massive complexity behind cargo. Why does anyone think it’s reasonable to pull in dozens of online (!) dependencies for trivial code (node.js all over again), and with Rust you can’t get around this bloat.

                                      And I’m not even saying that this was about C vs. Rust. I am aware of the advantages Rust offers.

                                      But the bloat is unnecessary. Consider Ada for example, which is way more elegant and provides even more security than Rust.

                                      1. 14

                                        Cargo is simple technically. Probably simpler than cmake and dpkg.

                                        Rust uses many dependencies, but that isn’t necessarily bloat. They’re small focused libraries. Slicing a pizza into 100 slices instead of 6 doesn’t make it any larger. I have 45 transitive dependencies in libimagequant, and together they are smaller than 1 OpenMP dependency I’ve had before.

                                        Cargo uses many small deps, because it’s so easy and reliable, that even trivial deps are worth using. I don’t think pain should be the driving factor technical decisions — deps in C are a pain whether they’re used justifiably or not. Even despite dependency friction C has, applications still use many deps. Here’s a recent amusing example of dependency bloat in vim.

                                        I’ve considered Ada, but it offers no safety in presence of dynamic memory allocation without a GC. The usual recommendation is “then just don’t allocate memory dynamically”. That’s what I’m aiming for in C and Rust too, but obviously sometimes I do need to allocate, and then Rust offers safety where Ada doesn’t.

                                        1. 6

                                          The usual recommendation is “then just don’t allocate memory dynamically”

                                          Ada allows you to declare anything pretty much in any declaration block, including run-time sized arrays, functions, variables, tasks, etc. so a lot of time you’re logically “allocating” for work, but it’s usually stack allocated though the compiler can implicitly allocate/free from the heap (IIRC). Being able to return VLAs on the secondary stack also simplifies things a bit like returning strings. The standard library is pretty extensive too, so you usually just use stuff from there which will be RAII controlled. Between RAII via “Controlled types” and limits on where access types (pointers) can be used, I don’t think I’ve ever actually seen raw allocations being passed around. Implicitly passing by reference when needed, and allowing declaration of different pointer types to the same thing, but declared in different places seems to really cut down on pointer abuse.

                                          One of my Ada projects is ~7000 LoC (actual, not comments or blanks) and I have one explicit allocation where I needed polymorphism for something, wrapped in a RAII smart pointer which also allocates a control block.

                                          Looking at Alire, ~28600 LoC (actual, not comments or blanks), shows only 1 allocation which doesn’t go through the program lifetime, which is inside an RAII type. If you include all 1554 files of it and its dependencies, Unchecked_Dellocation only appears in 60 of them.

                                          I understand the disbelief. I get that it’s weird.

                                          (shrug), I dunno, it’s sort of hard to explain, but the language and standard library means you just often don’t need to allocate explicitly.

                                        2. 9

                                          This is a strawman argument, because Cargo’s package management features aren’t what we were talking about. But you can use Rust without needing to depend on any other packages, in fact you can use it without Cargo at all if you want, just create a Makefile that calls rustc. Saying that you “can’t get around” this bloat is not really factual.

                                          1. 1

                                            How far is this going to get you when the standard library doesn’t even include the most basic of things?

                                            Packagers (rightfully) won’t touch rust-packaging as the majority uses cargo and everything is so scattered. When you are basically forced to pull in external dependencies, it’s reckless, on the other hand, not to rely on cargo.

                                            Ada does it much better and actually reflects these things, and C benefits from a very good integration into package management and systems overall.

                                            Rust could’ve had the chance to become easily packagable, but it isn’t. So while the “move fast”-philosophy definitely helped shape the language, it will lead to long-term instability.

                                            1. 12

                                              As someone who occasionally packages rust things (for Guix) I don’t really know why everyone thinks it’s so hard. Cargo metadata for every project means you can often automate much of the packaging process that in C I do by hand.

                                              1. 2

                                                Given you seem to have experience with this, how simple is it to create a self-contained tarball of a program source with all dependencies (as source or binary) that does not require an internet connection to install?

                                                1. 14
                                                  1. 2

                                                    Nice, I didn’t know about that one. Thanks!

                                                  2. 6

                                                    Note that this isn’t a requirement for all packaging systems. The FreeBSD ports tree, for example, requires only that you be able to download the sources as a separate step (so that the package builders don’t need network access). There’s infrastructure in the ports tree for getting the source tarballs for cargo packages from crates.io. These are all backed up on the distfiles mirror and the package build machines have access to that cache. All of the FreeBSD packages for Rust things use this infrastructure and are built on machines without an Internet connection.

                                                    1. 1

                                                      Very interesting, thanks for pointing that out!

                                                2. 5

                                                  Just because you like C and Ada doesn’t mean every other language is terrible.

                                                  1. 1

                                                    I totally agree. For instance I love Julia for numerics.

                                        1. 18

                                          Rust, of course, is the only language in existence which offers run-time memory safety without garbage collection.

                                          I’m not sure if this holds, for instance, Swift does memory management without using a GC.

                                          1. 13

                                            And ATS, which provides the ability to do pointer arithmetic and dereferencing safely without garbage collection. In general, claims of “only one that does” and “first to do” should be avoided.

                                            1. 5

                                              ATS is the first language to have a “t@ype” keyword.

                                              1. 3

                                                ATS is very interesting! thanks for sharing it

                                                1. 2

                                                  Check out Aditya Siram’s “A (Not So Gentle) Introduction To Systems Programming In ATS,” it’s a great overview.

                                              2. 11

                                                It depends a bit on how you define garbage collection. I’ve seen it used to mean both any form of memory management that does not have explicit deallocation or specifically tracing-based approaches. Swift inherits Objective-C’s memory management model, which uses reference counting with explicit cycle detection. Rust uses unique ownership. C++ provides manual memory management, reference counting, and unique ownership.

                                                1. 6

                                                  Rust uses unique ownership. C++ provides manual memory management, reference counting, and unique ownership.

                                                  Both Rust and C++ provide all three.

                                                  1. 4

                                                    The problem is that C++ can also provide stuff you don’t want in your code usually - without using an unsafe {}.

                                                2. 5

                                                  Ada meets that definition, too.

                                                  Even modern C++ could claim to have run-time memory safety without GC, but that obviously requires the developer to use it correctly.

                                                  1. 5

                                                    Ada isn’t completely memory safe, though I would say it’s a lot safer than C or C++ with all of the additional built-in error checking semantics it provides (array bounds checks, pre/post conditions, numeric ranges, lightweight semantically different (derived) numeric types, type predicates). I’ve found it hard to write bugs in general in Ada-only code. It’s definitely worth checking out if you haven’t.

                                                    As for modern C++, it feels like we made these great strides forward in safety only for coroutines to make it easy to add a lot of silent problems to our code. They’re super cool, but it has been a problem area for myself.

                                                    1. 3

                                                      Rust is also not completely memory safe: it has an unsafe escape hatch and core abstractions in the standard library as well as third-party frameworks require it.

                                                      1. 2

                                                        I agree. Not a lot of people are familiar with Ada, so my point was to dispel the myth it is completely safe, while also answering the common reply I’ve seen that “Ada isn’t memory safe, hence you shouldn’t use it.”

                                                  2. 3

                                                    Isn’t atomic reference counting a form of GC as well?

                                                    1. 4

                                                      One could say that everything that deviates from manual memory management is some form of GC. Still, we do have the traditional idea that, generically speaking, GC implies a background process that deallocates the objects asynchronously at runtime.

                                                      1. 3

                                                        If you think about it, stacks are GC because they automatically allocate and deallocate in function calls. 🤔 That’s why they were called “auto” variables in early C.

                                                        Galaxy brain: malloc is GC because it manages which parts of the heap are free or not. 🤯

                                                        1. 1

                                                          ahahah great viewpoints, wow I learned so much with your comment, it got me looking into “auto” C variables. never realised that all vars in C are implicitly auto because of the behaviour that they get removed when they go out of scope 🤯 (I wonder how did they got explicitly removed back then? and how it all relates to alloca()? could it have been designed that way to allow for multiple stacks at the same time with other segments besides the stack segment?)

                                                          that last bit about malloc is amazing, it is indeed managing virtual memory, it is us who make the leaks 😂

                                                          1. 1

                                                            all vars in C are implicitly auto because of the behaviour that they get removed when they go out of scope 🤯 (I wonder how did they got explicitly removed back then?

                                                            Back in the day, as I understand it, there was no “going out of scope” for C. All the variables used by a function had to be declared at the very top of the function so the compiler could reserve enough stack space before getting to any code. They only got removed when you popped the stack.

                                                  1. 4

                                                    Python is a huge mess. The entire time wasted on porting 2 to 3 and maintaining the messes would’ve better just been spent on porting Python software to better languages. Go and Rust are given here, but several others come to mind as well (Julia, Ada, etc.). I’m not a big Rust fan, but Python really takes the cake here and has wasted me personally a lot of time as well.

                                                    Using Gentoo myself, I always felt a bit uneasy considering the fact that my package manager is just running on an interpreter that could easily get shot or broken for some reason (which can happen in the case of Python if one simple environment variable is set incorrectly or a single supplementary file missing).

                                                    If they used Go, C or Ada (now that would be really cool!), they could statically link the critical programs and would also be more independent from the mess that the Python ecosystem is. However, I do understand they already have limited developer-time and other things to focus on, which sadly is fewer and fewer actual software updates and more and more “infrastructure” things and webshit-bloat infesting infrastructure that should not change every 1-2 years.

                                                    1. 1

                                                      Synth and the Ravenports admin tool are written in Ada.

                                                    1. 7

                                                      I am finishing up my Ada crate of the year entry.

                                                      1. 3

                                                        Goodluck! Post your entry when you’re done :)

                                                        1. 2

                                                          I actually already submitted a while ago. There’s a lot of additional work I want to do though, like better docs (especially about how config work), adding command history and improving caching and my VT100 support.

                                                      1. 1

                                                        I found that having a racked server to be exceptionally loud, distracting, and wasteful in terms of space. It was super heavy and I had put it into a rollable case, which took up too much room.

                                                        My home “server” for a long time was a Linux desktop I cobbled together from garage sale and thrift store parts. I tried my own rack mounted server at this point, and then after realizing the issues I got rid of it and I built a new Linux desktop to use as a home “server.”

                                                        1. 2

                                                          I equate modern software development to alchemy. There is actual progress being made, but also a long chain of mystical solutions (like Agile), purported to solve all our problems and make gold. There’s also a whole lot of money being thrown at developers by “patrons” to make a “Philosopher’s Stone” in several fields. This isn’t to say ways we do things don’t have portions of truth to them and work in specific contexts, but in 50 years we’ll laugh at the primitive constructs and methods we use today.

                                                          1. 2

                                                            There was an interesting result from, I think, the ‘70s that showed that changing your process yielded a roughly 10% increase in productivity for a team over about a six-month period[1] (it gradually settles back to the old level) and this was independent of what the old and new processes are. The corollary for this is that a team that keeps jumping on the latest buzzwordy methodology will be more productive than one that doesn’t, the quality of the buzzwords is largely irrelevant.

                                                            [1] From memory, the numbers are probably wrong.

                                                          1. 5

                                                            I’ll continue moving my personal organization/todo/knowledge base to my new Fossil setup. It has gone much better than expected. I got the basics set up and customized the ticket system a bit. I’m stoked for the simplicity of having a single file to backup. Still, I can sync this (including wiki/tickets) between multiple computers while keeping control of my own data.

                                                            1. 2

                                                              I am moving my personal electronic notebook over to Fossil. I had been using Sphinx, but I’m going to try to track notes with the wiki, and use the bug tracker as my personal todo list.

                                                              1. 2

                                                                Interesting, that would make a good blog post if it works out for you.

                                                              1. 3

                                                                Ada seems like an interesting language, but I wish this article was written better. A number of concepts, like attributes, are used without being explained, and there are number of confusing typos.

                                                                All that aside, I’m curious as to what would be the benefits of using Ada over something like OCaml which also has a good type system, modularity and these days a decent ecosystem with modern tooling.

                                                                1. 3

                                                                  I wish this article was written better

                                                                  I have my own writeup about Ada if you’re interested.

                                                                  number of confusing typos

                                                                  with ada.Text_IO; use Ada.Text_IO;
                                                                  

                                                                  Completely legal, but still a typo. Ada isn’t case sensitive, but normally you’d see Ada.Text_IO. I thought case insensitivity would be a huge deal breaker, but I never had issues with it in practice.

                                                                  -- while loop
                                                                     while myCount < 3 loop
                                                                  

                                                                  -- is a comment, not sure why they thought they needed a comment here.

                                                                  like attributes, are used without being explained

                                                                  It’s a built-in function or property associated with a type: 'Alignment for byte alignment, 'Length for array length, 'Succ for the next successive enum, 'Image for toString() like behavior, etc. Some can be overridden. It looks like the code formatter doesn’t support for notation, so it erroneously highlights the following code in the article.

                                                                  using Ada over something like OCaml

                                                                  Ada cross-platform support with Free Software Foundation’s GNAT (in gcc) is good. I have multiple programs which run on Windows and Linux, which include things like iterating over files/directories and concurrency (built into Ada) without changes.

                                                                  Ada supports package generics which are like OCaml’s signatures. I had to use the OCaml documentation to clarify what a signature was when I was learning it at the time. Being able to define ranges and your own type invariants is super helpful for modeling a problem, and built-in pre/post conditions help catch a few edge cases I missed.

                                                                  decent ecosystem with modern tooling

                                                                  It’s much better than I ever expected Ada to have. Alire is sort of like cargo except it also installs toolchains for you as well. There’s a language server and a Visual Studio Code integration which uses it. The tooling folks have been super responsive, I’ve gotten bugs and feature requests fixed in a day or so before.

                                                                  1. 2

                                                                    Thank you! This was very useful. I will check out your article.

                                                                    1. 1

                                                                      That similarity isn’t accidental: both module systems are descendants of Wirth’s Modula-2 module system.

                                                                      I prefer OCaml for most use cases myself, but I don’t think there’s anything better than Ada right now for embedded applications, especially if they are safety-critical. Range types, type-safe approach to pointers, etc.—it’s high-level and expressive but also close to the machine, and suitable for hard realtime.

                                                                  1. 3

                                                                    I used the cargo-like Alire instead of gnatmake, but I found Ada to be an enjoyable language to toy around in when I learned it earlier this year.

                                                                    1. 2

                                                                      I am somewhat interested in Ada, but there is absolutely no way that I’d take a dependency on a language where the only F/OSS implementation is GPLv3. It’s a shame that AdaLabs’ effort to write an LLVM front end for Ada didn’t work out.

                                                                      1. 2

                                                                        LLVM compiler is still work in progress. Also few more compilers coming up. Foss GPLv3 is now with exception license also

                                                                    1. 2

                                                                      I am getting house plants, English Ivy and maybe Peace Lily to clean the air indoors. I already have a few Pothos (Devil’s Ivy) who I’ve had to bring back from the dead a few times, but with decreasing frequency, so I’m ready for more of a challenge.

                                                                      I’m trying to wrap up my current project and then I’m going to wrestle with the angst of C++ vs. Ada vs. Rust since I like and I’m familiar with all three and can’t choose what to do my next project in.

                                                                      1. 4

                                                                        I’ve been running this and the previous release candidates for a while. Ada having a package manager that also downloads the FSF toolchain is very convenient across multiple setups and in CI. Much improved dependency pinning also makes it easy to split your project into multiple libraries and develop both simultaneously.

                                                                        1. 1

                                                                          I am in code cleanup and stabilization mode. I wrote my own terminal input library and I got tab completion and custom line formatting working in an interactive tool which needs it. For example: directory completion on tab works and if you’re inputting a command or a regex, it’ll turn green or red depending on if it’s valid or not. I’m struggling a bit since I’m don’t want to lock in a bad API by publishing the new version of the library which does this.

                                                                          1. 5

                                                                            I take “boring” to be subjective to the person and the problem. I’ve written C and C++ for years, so it’s “boring” to me, but it’s not to many other people. I haven’t used Java in probably a decade, so I wouldn’t consider that “boring”.

                                                                            When I’m doing “interesting work” I want to focus on the problem, not on mechanics of how to write it, or get the code to run. I’ll write it in a language and environment I understand well and then port into whatever I need. I try to keep languages in my toolbox which are good at different things and use whatever is the closest line to done given the project.

                                                                            1. 5

                                                                              Yeah, Java isn’t boring it’s just… I have no reason to use it? Even if I was forced into the JVM for some reason there are very stable options that don’t give all the pain Java gives.

                                                                              1. 1

                                                                                There have been so many changes to Java since I last used it that I’m kind of interested in it now.

                                                                              1. 5

                                                                                One thing about Ada I’d like explained better is dealing with safety of dynamically allocated memory. The usual answer I see is “you just avoid allocating memory” which is underwhelming. Everyone already avoids allocating memory, so this feels like dodging the question.

                                                                                1. 3

                                                                                  I must say, after I’ve learned some Ada I also became somewhat more skeptical about Ada’s safety even without memory allocation. Ada has uninitialized variables, data races and mutable aliasing-related type confusion out of the box — you actually need SPARK to guarantee even program integrity.

                                                                                  I don’t know how big of a deal that is in practice: intuitively, it still seems way way better that C’s collection of dangerously sharp objects.

                                                                                  1. 1

                                                                                    Yes, it’s nowhere near as safe as the evangelists say. Its semantics are equivalent in power to any C-style language. Of course it’s better than C because it avoids a lot of undefined behavior and has less “features” designed to circumvent the type system, but semantically it is very weak. It’s no wonder that Ada is being replaced by C++ and not some other language with safer inherent semantics. The type of C++ static analysis tools people who use Ada use already dull C++’s sharp corners, and the difference in semantic power is minimal.

                                                                                    1. 1

                                                                                      Ada definitely isn’t safe, but it’s harder to shoot myself in the foot than with C or C++.

                                                                                      mutable aliasing-related type confusion

                                                                                      Thanks, that’s an interesting example which still works on FSF GNAT 10.3! That’s a very atypical combination of infrequently used features (variant record, fields with vtables in a variant, defaulted discriminant, global state with a procedure operating on that state) to get there. I’m keeping that on hand to remind myself how I can be bitten by it. I don’t think that expression, M := should error at compile-time, discriminants are supposed to only be bound once, but only since it has a defaulted discriminant, the unassigned value M : Magic is allowed and also that assignment.

                                                                                      uninitialized variables

                                                                                      The compiler is usually pretty good about ensuring you initialize things if you forget, with a few exceptions, like mentioned above. The one time this bit me was in a defaulted aggregate, where I set all remaining fields in a record to their “default” values, and one didn’t have one: Var := (FieldA => ValueA, FieldB => ValueB, others => <> ). Supposedly pragma Normalize_Scalars is supposed to help with this.

                                                                                      data races

                                                                                      Ada’s protected objects help deal with data races in a pretty interesting way, which can include arbitrarily complex conditional guards on access, in addition to operating like a mutex. You have to make sure your data is set up that way though.

                                                                                      “you just avoid allocating memory”

                                                                                      Yeah, it seems really, really weird to hear people say that, and I was originally very skeptical about it. After a while of working in Ada, you realize it’s similar to C++ where you wrap you have containers and other resources usually wrapped in RAII (controlled) types and just forget about it. The few times I’ve needed allocations, I’ve used a RAII-based reference-counted pointer. The other reason you don’t deal with many allocations is that you can return variable-length arrays with their bounds on the stack, and implementations are required to check for stack overflow.

                                                                                    2. 2

                                                                                      Ada is not memory safe in the presence of dynamic memory deallocation. There is no solution to this problem in Ada. Even the deallocation function is named Unchecked_Deallocation .

                                                                                    1. 7

                                                                                      Which doesn’t address the reason that I’ve seen for avoiding Ada:

                                                                                      There is one open source implementation and it is owned by an organisation that has already changed the license in an incompatible way once, picking one that was unacceptable even for internal use, to a number of companies.

                                                                                      Ironically, the existence of clang has helped a number of places stay with GCC for C/C++ because they have a second source if the FSF’s future licensing policy becomes unacceptable to them. There’s no equivalent for Ada.

                                                                                      AdaLabs was looking at doing an LLVM Ada front end in the past but didn’t make much progress. Until that exists, I wouldn’t recommend any company use Ada: even if taking a dependency on a GPLv3 toolchain with a GPLv3 + runtime exemption library is acceptable (which it isn’t for a lot of places), there’s no guarantee that a dependency on a GPLv4 toolchain with a GPLv4 + runtime exemption library is going to be.

                                                                                      1. 3

                                                                                        There’s an LLVM front end in progress. I haven’t tried it out yet, but it seems to be under active development.

                                                                                        1. 2

                                                                                          That’s connecting the GNU front end to an LLVM back-end. The same thing worked with DragonEgg (which did GIMPLE to LLVM IR translation and so worked with GNAT and other GCC front ends). It doesn’t remove the dependency on the good graces of the FSF.

                                                                                          1. 1

                                                                                            Ah, thanks, I see your point now, I hadn’t thought about that.