[HN Gopher] A Random Walk Through Ada (2014)
___________________________________________________________________
A Random Walk Through Ada (2014)
Author : okl
Score : 48 points
Date : 2024-11-09 00:57 UTC (22 hours ago)
(HTM) web link (cowlark.com)
(TXT) w3m dump (cowlark.com)
| guenthert wrote:
| > It being a one-pass compiler bugs me (there is no excuse for a
| modern language to require forward declarations).
|
| He refers to the need for forward declarations as "one-pass
| compiler". Historically at least, Ada compilers were infamous for
| requiring many passes and being consequently slow.
|
| Whether it is still acceptable for a programming language to
| require forward declaration seems to me rather a matter of
| personal taste. Sure, compilers improved and there's plenty of
| memory for them to use, but human programmers' capacity increased
| little, if any, I'd think. I think of those forward declarations
| as form of double-entry bookkeeping.
| kevlar700 wrote:
| Interesting. I love Ada and these historical doomed to repeat
| ourself facts are interesting like Ada books from the 80s
| talking about AI. Before I switched from Go to Ada I actually
| used to use var upfront out of preference.
| roland35 wrote:
| I once did an engineering camp at the Air Force academy and in
| one of the classes we programmed Lego mindstorms with Ada -
| something like https://www.adacore.com/academia/projects/real-
| time-mindstor...
|
| I do wish we had better options for embedded! Even C++ isn't
| making much headway against C when it comes to programming
| microcontrollers.
| kevlar700 wrote:
| Ada is so good for embedded. Loving it.
| pjmlp wrote:
| Mikroe is still in business selling BASIC and Pascal compilers
| for microcontrollers, so some do pay for them.
| adrian_b wrote:
| There is a phrase that might be confusing for those who do not
| know Ada:
|
| "As a historical note, earlier versions of Ada forbade reading
| from out variables, which allowed more efficient calling
| conventions, but modern Ada allows it because otherwise people
| went insane."
|
| What is meant is that the "out" parameters behave like local
| variables without initializers, which upon entry into a function
| are likely to have invalid values.
|
| Therefore you cannot read an "out" parameter before assigning a
| value to it. After the first assignment, it can be read or
| written at any time before the function returns.
|
| Depending on the type, an "out" parameter is implemented as
| either a CPU register whose value is unknown upon function entry
| or as a reference to a memory area allocated in the caller, but
| uninitialized.
|
| The specification of the function parameters as "in", "out" or
| "in out" and the irrelevance and transparency of how the compiler
| chooses to pass the parameters is one of the best features of
| Ada.
|
| This has not been invented by the creators of Ada, but it has
| been invented by some anonymous Department of Defense employees
| or contractors.
|
| This feature was included in the DoD "Requirements for High Order
| Computer Programming Languages", "IRONMAN" from the July 1977
| revision. It was probably already present in the first version of
| "IRONMAN" from January 1977.
|
| It is a huge mistake in the design of almost all programming
| languages that have appeared after Ada that they do not include
| this feature.
|
| The lack of distinction between "out" and "in out" parameters has
| serious consequences especially for the object-oriented
| languages. The lack of this feature has caused a very large part
| of the complexity of C++ and also most of the performance
| problems of the C++ versions from before 2011.
|
| When "out" and "in out" parameters are distinguished, there is no
| need for the existence of constructors as a separate concept. Any
| ordinary function with an "out" parameter can be used wherever
| C++ requires a dedicated constructor. Instead of constructors, it
| is enough to have an identifier convention for functions that
| should be called by the compiler when you want implicit
| initialization or implicit conversions.
|
| Moreover, there is no need to care about "copy" semantics and
| "move" semantics or about temporaries which are or which are not
| generated by the compiler. It is easy for the compiler to always
| choose the best implementation without programmer intervention,
| when it knows the correct parameter modes for the functions.
| Thorrez wrote:
| >When "out" and "in out" parameters are distinguished, there is
| no need for the existence of constructors as a separate
| concept. Any ordinary function with an "out" parameter can be
| used wherever C++ requires a dedicated constructor. Instead of
| constructors, it is enough to have an identifier convention for
| functions that should be called by the compiler when you want
| implicit initialization or implicit conversions.
|
| Why do we need "out" vs "in out" parameters for this? Why can't
| a function that returns the object work just as well? And "an
| identifier convention for functions that should be called by
| the compiler when you want implicit initialization or implicit
| conversions" seems essentially the same as constructors to me.
|
| >Moreover, there is no need to care about "copy" semantics and
| "move" semantics or about temporaries which are or which are
| not generated by the compiler. It is easy for the compiler to
| always choose the best implementation without programmer
| intervention, when it knows the correct parameter modes for the
| functions.
|
| How would I implement something like std::vector with deep copy
| and move support of its contained objects without writing copy
| and move constructors (or operators)? There needs to be code
| saying "allocate a new block of memory and copy all the
| elements to that new block", and code saying "just copy the
| pointer, and set the other pointer to null". Are you saying the
| implementer would still write that code, just not in
| constructors/operators? How is that better?
| pyjarrett wrote:
| The big reason for `out` only is "I want to write here, but I
| don't care about the initial value." It's a more explicit
| version of the C++ `Foo& outFoo` output parameter paradigm.
|
| > When "out" and "in out" parameters are distinguished, there
| is no need for the existence of constructors as a separate
| concept.
|
| I don't agree with this. You can get I need to do things
| "post-init" with controlled types, or use a `return X : Thing
| do ... end return` block. Constructors help ensure
| invariants. You can make a type `is private` to prevent
| instantiation, only allowing creation via functions (sort of
| like Rust `new` associated functions), or initialization via
| an `out` param. It's OK but not perfect, but you can also tag
| on a `Type_Invariant` aspect if there are conditions which
| have to be met by a type. My big problem with Controlled
| types is that forces a type to be `tagged` (i.e. it has a
| vtable) which means it affects storage layout of values of
| that type, which isn't a problem in C++.
|
| You can forbid copies by making something a `limited` type,
| but you'd have to write your own "Move" equivalent, and some
| of the containers have `Move` subprograms implemented to
| transfer contents. Limited types might elide the copy when
| returned from a function, but it's been a while since I
| looked at those rules.
| adrian_b wrote:
| In C++ or similar languages, where the function parameters
| behave semantically as either "in" or "in out" parameters, a
| function that returns an object must have already created
| somehow the object.
|
| Therefore calling a function just adds a task of invoking a
| constructor also into the function, it cannot replace a
| constructor.
|
| In C++, an object cannot be created by assigning a value to
| it, because the left hand parameter of the assignment
| operator is an "in out" parameter, like for any other
| function, so it is assumed that it already has a value of the
| type of that object.
|
| Therefore an assignment operator must execute the equivalent
| of invoking a destructor for the target of the assignment,
| followed by the invocation of a copy constructor.
|
| Attempting to assign a value to memory allocated but not
| initialized will attempt to invoke a destructor for an
| invalid object value.
|
| The constructors are the only C++ functions that implicitly
| have a result which is an "out" parameter, not an "in out"
| parameter, like the other functions.
|
| Because the memory where the result of the constructor will
| be placed is not initialized, no destructor must be invoked
| for it, so all will be OK.
|
| All these rules about when to use constructors and when to
| use functions and the need to have duplicate almost identical
| in meaning functions for certain purposes, e.g. copy
| constructors and assignment operators, complicates a lot C++.
|
| Any copy or deep copy operations would be implemented very
| simply, just by copying what needs to be copied.
|
| There would be no need for "move" operations of any kind,
| which are just a trick to avoid the inefficient code
| generated by compilers when the semantics for some parameters
| is "in out" when what would have really been needed is "out".
|
| Specifying that some functions are not normal functions, but
| constructors, or that some operations have "move semantics"
| is just an extremely complicated way to specify that some
| function parameters are "out", not "in out". Besides being
| hard to understand, these tricks only work in particular
| cases, instead of being able to specify the mode of any
| function parameter.
|
| In a language with distinction between "in out" and "out",
| the mode for the result of assignment is naturally "out" and
| there is no need for the contortions of C++. In such a
| language a compiler knows when to invoke destructors and when
| not to invoke them and it knows when no extra temporaries are
| needed for computing a complex formula with objects.
| GregarianChild wrote:
| A different world, but Verilog has in, out and inout
| parameters, too.
| pyjarrett wrote:
| I recently started writing Ada again, a couple of years after I
| did a bunch of projects with it. The amazing things is how easy
| it is to go back and update old code due to how much semantic
| information gets embedded in it and how few symbols it uses.
| tolerance wrote:
| Few things can draw your attention to subjects that you don't
| understand better than appealing visual design and clear
| language.
| ajdude wrote:
| For those interested in trying Ada out, I wrote a a Rustup-like
| app that installs Ada's package manager (Alire) on macOS and
| Linux: https://www.getada.dev
|
| It was also featured on HN (194 points | 6 months ago | 117
| comments: https://news.ycombinator.com/item?id=40132373
|
| I've gone from not having anything Ada related on my computer to
| installing the toolchain, initiating a project , writing,
| compiling, and running "Hello World" in less then 2 minutes.
|
| Ada has had something of a resurgence in the last couple years,
| with the latest standard (2022) officially released and for the
| first time in a few years, Ada has its own dev room at FOSDEM!
| https://fosdem.org/2025/news/2024-10-28-devrooms-announced/
|
| There's also a growing community at ada-lang.io with a thriving
| forum: https://forum.ada-lang.io/
| Jtsummers wrote:
| https://learn.adacore.com
|
| A collection of less random and more up to date walks through Ada
| if this piqued your interest. It's been kept up to date with the
| latest language features and more tutorials. Also, helpfully, has
| comparative tutorials to see some features side-by-side in Ada,
| Java, C++, and C.
| dang wrote:
| Related:
|
| _A Random Walk Through Ada (2014)_ -
| https://news.ycombinator.com/item?id=12850919 - Nov 2016 (88
| comments)
|
| _A Random Walk Through Ada (2014)_ -
| https://news.ycombinator.com/item?id=9674408 - June 2015 (14
| comments)
___________________________________________________________________
(page generated 2024-11-09 23:01 UTC)