[HN Gopher] Summary After Four Months with Ada
___________________________________________________________________
Summary After Four Months with Ada
Author : thindil
Score : 264 points
Date : 2021-08-29 07:22 UTC (15 hours ago)
(HTM) web link (pyjarrett.github.io)
(TXT) w3m dump (pyjarrett.github.io)
| bb88 wrote:
| I would hesitate to call Ada "obscure", though. Maybe "once
| popular" -- especially since DoD spent billions writing Ada.
| MaxBarraclough wrote:
| An interesting read, but there's an error:
|
| > Unfortunately, the top tiers of [SPARK] analyses are paid only,
| but you can get data/information flow analyses, as well as
| guarantee of no runtime errors for free.
|
| That's not right. Straight from AdaCore's Yannick Moy, a year
| ago: [0]
|
| > _SPARK as included in GNAT Community allows you to go up to
| platinum level, with the 3 provers included (Alt-Ergo, CVC4 and
| Z3)_
|
| [0]
| https://old.reddit.com/r/ada/comments/hwgbwa/survey_on_the_f...
| pyjarrett wrote:
| Thanks for pointing this out. Fixed.
| MaxBarraclough wrote:
| Speedily done, thank you.
| alex_duf wrote:
| Ada was the first language I learned through my Computer Science
| courses during my University years (Bayonne, France).
| pjerem wrote:
| Same for me at University of Nantes (France).
|
| Unfortunately, I was too narrow-minded to understand that it
| was a really interesting langage and not just a useless
| academic hobby of my teachers.
|
| At least I do now, but I'm sad I was not more attentive at this
| time.
| jabl wrote:
| I wonder how much more robust the software we all interact
| with daily would be, had Ada become the standard systems
| programming language instead of C and C++.
| Jtsummers wrote:
| As much as I like Ada, there were a couple projects at an
| old office that were great demonstrations that you could
| write C code in any language. Among other things, they
| absolutely failed to understand the type system so had a
| lot of manual range checks instead of letting the compiler
| and automatically generated runtime checks do the work for
| them. They didn't understand how to loop over arrays,
| passing in size information as a parameter. It was gross
| code, like someone had simply translated C or Fortran to
| Ada without consideration of the target language's
| abilities.
|
| It would be like someone choosing Rust and then making
| everything unsafe. Or Haskell (I saw this in a tutorial
| once, it was hilarious and disgusting at the same time) and
| using strings (data) for dispatch instead of translating
| them into types and actually exercising the type system.
|
| All that is to say, thoughtless programmers outnumber
| thoughtful ones. The language can only take you so far.
| mcculley wrote:
| I worked with Ada a lot during the 90s (and even maintained the
| Linux port of GNAT early on). This document does not address one
| thing that I am curious about. What does the modern, idiomatic
| Ada programmer do about memory management? Are library
| implementers still required to use Unchecked_Deallocation? I
| don't see how a language where Unchecked_Deallocation is used can
| be considered safe at a time when we have modern choices with
| automatic memory management.
|
| Edit: I guess another way to put this is, "Can a non-trivial
| project be developed in modern Ada without using
| Unchecked_Dealloation?" Because I don't see how I can consider a
| library safe if it is allowed to call Unchecked_Deallocation.
| geofft wrote:
| Not having written Ada, but having seen many HN naysayers
| saying "Why do we need Rust when Ada can do this" and having
| tried to come up with a well-researched rebuttal, my sense is
| that there are three options:
|
| 1. Your project is _static_ enough that it doesn 't need
| dynamic memory allocation. The control system for a modern
| passenger jet is a pretty complex project, but you can allocate
| an object per engine, an object per flap, a struct per landing
| gear, an object per pilot display, etc. at design time. Even
| the navigational computers on these aircraft, which take in
| unbounded structured data about airports and navigational
| points, often have hard-coded limits. Quoting
| https://www.mitre.org/sites/default/files/pdf/12_1324.pdf :
|
| > _one widely used FMC [flight management computer] model ...
| has issues at airports with over 100 arrival and departure
| procedures. Some airport examples where 100 arrival and
| departure procedures are exceeded include Cairo, Amsterdam,
| Madrid, Paris (Le Bourget, Orly and Charles de Gaulle), Mumbai,
| New Delhi and Beijing. A FMC service bulletin issued states
| that the aircraft may lose FMC applications in flight with over
| 100 procedures and flight plan up-linking. Further, another
| manufacturer has a FMC model with a limit of 99 total
| procedures and a limit of 8 waypoints per procedure. A third
| FMC manufacturer has a model with a limit on the amount of
| arrivals, departure and approaches as shown below: Early models
| - limit of 70 departures, 70 arrivals, and 29 approaches at an
| airport. Later models - limit of 130 departures, 130 arrivals,
| and 39 approaches at an airport._
|
| Counterintutitively, this is culturally acceptable for such
| "high assurance" applications, but WhatsApp gets confusion from
| the press when it increases the maximum number of participants
| in a group chat to the "oddly specific number" of 256
| (https://i.redd.it/gk7dicv6hsvy.jpg).
|
| 2. You use a third-party GC/refcounting library that calls
| Unchecked_Deallocation internally.
|
| 3. There's a 2018 proposal (linked in another reply) for
| "ownership types", which specifically references Rust's
| lifetime model as an inspiration.
|
| Or, in other words, if your goal is to write a (say) safe
| implementation of the DOM that can render real-world web pages
| while efficiently using memory on a general-purpose computer,
| Ada is probably the wrong tool for the job. Which is fine! It's
| a great tool for other jobs.
| joakimds wrote:
| Hi Geofft! Ada developer here. When I read and study the Ada
| reference manual for the 1995 standard I get the impression
| that the Ada language designers were not thinking of third-
| party garbage collection or reference counting as the primary
| way of achieving memory safety but they were thinking of
| arena pools/storage pools. When one defines an access-to-
| object type in the 1995 standard one can specify in which
| storage pool the allocated object ends up in. The Ada
| standard does not talk about Stack and heap but talks about
| Stack and Storage pools. I get the impression that the idea
| is for an Ada application to get a number of storage pools
| (with statically determined sizes?) and one can allocate
| objects inside of these and when one is finished with the
| objects in a pool one deallocates them all at once by
| emptying the pool and then one can reuse it again. More
| efficient and less-error-prone than deallocating each object
| separately. You are right in point number 2 that the door for
| garbage collection is open in the Ada standard. No Ada
| compiler vendor has implemented a GC but you are right about
| it being considered. The idea for arena pool/storage pool can
| also been seen in the Ada language (also 1995 standard) by
| being able to define an access-to-object type locally inside
| a function/subprogram and at the point of the access-to-
| object types existence some memory is heap allocated (the
| size of the allocated memory is specified by the access-to-
| object type definition) and when the access-to-object type
| goes out of scope the memory is deallocated (without the use
| of unchecked_deallocation)... so there should be a forth
| point on arena/storage pools on your list. And it may be more
| suited for "a (say) safe implementation of the DOM that can
| render real-world web pages while efficiently using memory on
| a general-purpose computer".
|
| To use storage pools in Ada I would recommend Deepend
| (https://sourceforge.net/projects/deepend/). Deepend is a
| storage pool with subpool capabilities for Ada 2012, Ada
| 2005, and Ada 95. Memory allocations can be associated with
| subpools and subpools can be deallocated as a whole which
| provides a safer alternative than managing deletions of
| individual objects. It also is likely to be more
| deterministic and efficient than garbage collection.
| pyjarrett wrote:
| > if your goal is to write a (say) safe implementation of the
| DOM that can render real-world web pages while efficiently
| using memory on a general-purpose computer, Ada is probably
| the wrong tool for the job.
|
| Author here. Ada is actually perfect for the use case you
| listed. As a C++ programmer focusing on performance, the
| applicability of Ada to "modern problems" was one of the
| reasons I was playing around with it. Between customizable
| "storage pools" (Ada's allocators), the easy of interfacing
| with C, control of type alignment and layout, compiler
| intrinsics, built-in concurrency types (protected objects for
| coordinating access, and tasks for splitting work) and a
| bunch of other things, I have all the tools I need to do
| this. It's pretty close to the C++ feature set with the face
| of Pascal, and C++ programmers should feel comfortable
| working in Ada after only a few months.
| djur wrote:
| I don't think C++ was the standard intended here for "right
| tool for the job", but Rust. The quoted example project is
| a reference to Servo, if I'm not mistaken.
| pyjarrett wrote:
| I figured this was what he was referring to, but C++ is
| more familiar to a lot of people right now, which is why
| I couched my answer in those terms. Ada would still a
| good language to that work in.
| guerby wrote:
| "Are library implementers still required to use
| Unchecked_Deallocation?"
|
| Unchecked_Deallocation has more in it than just returning
| storage to the system, it also triggers Finalization:
|
| http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-13-11-2...
|
| "when X is not equal to null first performs finalization of the
| object designated by X (and any coextensions of the object
| ...)"
|
| So even if your compiler target has automatic memory management
| (eg: JVM) you will still use Unchecked_Deallocation if you want
| to control when Finalization occurs.
| pyjarrett wrote:
| > What does the modern, idiomatic Ada programmer do about
| memory management?
|
| Author here. I've actually not had to do any heavy direct
| memory management yet. There's an RAII-based (i.e. Controlled
| Type) reference-counted pointer implementation in GNAT I've
| used and the container libraries is mature enough to avoid the
| issue by just using built-in data structures.
|
| A few other smart pointer implementations exists floating
| around in various libraries in Alire, I suspect there will be a
| default one will appear in Alire at some point which parallels
| Rust's Arc, Rc and Box, or C++'s std::shared_ptr, std::weak_ptr
| (for breaking cycles) and std::unique_ptr. I have a partial
| implementation myself, but I've been working on other things.
| MaxBarraclough wrote:
| You might be interested in this thread from a year ago, where
| we discussed memory management in Ada. [0]
|
| The Ada folks sometimes seem a bit quiet on memory-management
| questions, a bit like the way Forth folks rarely talk about the
| real-world performance of Forth interpreters. On the plus side,
| borrower-checking is coming to SPARK. [1][2]
|
| [0] https://news.ycombinator.com/item?id=24361992
|
| [1] https://www.adacore.com/papers/safe-dynamic-memory-
| managemen...
|
| [2] https://arxiv.org/abs/1805.05576
| InfiniteRand wrote:
| One thing to keep in mind in Ada is the "typical" Ada
| programmer lives in embedded world, where memory needs to be
| deterministic. It's a very different perspective from say
| "desktop-application" world where dynamically allocating
| memory is just a natural part of programming.
| mcculley wrote:
| I get that. I just keep seeing Ada recommended for projects
| other than embedded systems and I don't see how it can
| work.
| [deleted]
| pyjarrett wrote:
| I found it a lot easier than I thought it would be. Ada
| has RAII (controlled types) which you can use for
| reference counting and resource management like in C++.
|
| Septum uses a lot of dynamically allocated memory, but
| it's all hidden by smart pointers or Unbounded_String
| (built-in reference-counted COW strings). I use it
| routinely to search codebases in the tens of millions of
| lines and it's fast enough right now (single second
| search times) due to task parallelism I did in Ada that I
| haven't even bothering to tune it or do any fancy
| indexing yet.
| [deleted]
| MaxBarraclough wrote:
| Presumably that means you're vulnerable to issues with
| reference cycles?
| pyjarrett wrote:
| In theory, yes, I'm vulnerable to reference cycles, but I
| haven't run into this in practice. The GNAT smart pointer
| types supports weak pointers if I need it.
| MaxBarraclough wrote:
| I'm not especially knowledgeable about Ada, but looking
| at the docs for GtkAda, it seems they're able to do
| reference-counting with good ergonomics.
|
| https://docs.adacore.com/live/wave/gtkada/html/gtkada_ug/
| mem...
| zetalyrae wrote:
| Off the top of my head there are two ways:
|
| - Lexically scoped access types have storage pools that are
| destroyed when the type goes out of scope. This is similar to
| region-based memory management as in Cyclone[0].
|
| - Limited controlled types are a lot like linear types and
| prevent unwanted aliasing and ensure deallocation happens
| correctly, as described in this paper[1].
|
| [0]:
| https://en.m.wikipedia.org/wiki/Cyclone_(programming_languag...
|
| [1]: https://dl.acm.org/doi/10.1145/165354.165362
| mcculley wrote:
| I think I understand these. I think these solutions work
| where it is very clear what the scope of object should be.
|
| But what about cases in large projects with many developers
| where a library/package allocates an object on the heap and
| passes it back to a caller? Sometimes it is not clear who is
| responsible for deallocating the object. This is the
| challenge we ran into building large projects in C, C++, and
| Ada. These days, I use Java, C#, Rust, or Go, because I know
| there will be no dangling pointers.
| zetalyrae wrote:
| >a library/package allocates an object on the heap and
| passes it back to a caller
|
| Limited controlled types handle this case.
|
| Limited types prevent assignment (i.e. aliasing).
| Controlled types introduce destructors so everything is
| closed even when an exception is thrown.
| mcculley wrote:
| I see how limited controlled types allow for reference
| counting. I don't see how they can be used to implement
| circular graphs and situations where it is not clear who
| needs an object to continue to exist.
| zetalyrae wrote:
| I haven't written enough Ada to know the answer (I've
| only researched the memory management scheme as part of
| implementing a language with compile-time ownership
| tracking).
|
| I think the Ada answer would be to keep everything that
| has a lifetime, anything that's a resource, in its own
| module behind a strict limited controlled interface. But
| that's a very vague answer.
| touisteur wrote:
| Yes you can and most of people in the embedded world doing Ada
| following mostly the same guidelines.
|
| 1- Don't use pointers. Or use not-null pointers. But preferably
| don't use them. With in/out semantics you don't need passing
| pointers or references around, and the addition of official
| data structures in Ada 2005 make most uses of pointers
| obsolete. 2- use controlled types when you're allocating to
| free soon. Limited_Controlled_Type are even safer if you're
| prepared to deal with a limited type :-) 3- recently, use
| SPARK, with safe-memory semantics. Hard work, but so is
| pleasing the borrow-checker... _edit_ Of course one of the
| impetuses (impetii) of manual memory management is having
| functions return objects of unknown size (at call site). In Ada
| this isn 't a necessity, at least with GNAT's secondary stack.
| _edit-end_
|
| I've programmed Ada almost every day of the work week for 13
| years now, I can count on one hand the problems related to
| memory management, and opening the code you _knew_ you were in
| for a treat. 'Smells like tiny cache syndrome' just remove
| those 90's blotches from our humongous codebases when we face
| them. I'm almost willing to make access types forbidden except
| in pools (so, not null he), with an open door policy 'explain
| to me so I can update our coding rules with that case if we
| find it worth the risk'. Forced software design review by
| linter.
| zmower wrote:
| Well, we do have a good set of generic containers now. Access
| types and Unchecked_Conversion have always been a code-smell
| IMO. And Ada is still foremost a realtime language so garbage
| collection just creates scheduling problems.
| mcculley wrote:
| I think that is a fine answer for limiting the applicability
| of Ada. I'm confused where people suggest it for bigger
| systems. I was on a team using it for a large soft real-time
| simulation. Memory management was a constant source of
| errors.
| joakimds wrote:
| I'm confused not more complex large-scale software projects
| are written in Ada. The way I understand it, they are not
| complicated enough you need Ada.
|
| For example, Ada makes it easy to structure one's code in a
| strict tree hierarchy (whenever you with a package put
| pragma Elaborate_All (..) on it, which works well with any
| Ada compiler I've tried it with and is in the Ada standard
| since 1995). It makes monolith creation by mistake
| impossible.
|
| Strange you had memory management problems in an Ada
| application. With all the focus on safety and security
| within the Ada community, it makes me wonder how the
| software engineers were using the language in that project?
| mcculley wrote:
| My understanding is that many safety critical systems in
| Ada don't allow for dynamic memory allocation or use of
| Unchecked_Deallocation. That's fine for systems where
| much is known at compile time. We were building software
| that could simulate thousands of entities. There was a
| lot of dynamic allocation. As soon as someone calls
| Unchecked_Deallocation, all bets are off with regard to
| safety.
| zmower wrote:
| I'm confused when people don't use it for bigger systems. I
| like that the compiler detects most of my errors before I
| run the program.
| mcculley wrote:
| My experience with bigger systems is that when you have
| 100 developers passing references around it becomes hard
| to manage who is responsible for deallocation of an
| object. This leads to dangling pointers and debugging.
| Going to languages with automatic memory management made
| such projects a lot more reliable.
| zozbot234 wrote:
| Rust surfaces this information as part of the type and
| lifetime system. There's no ambiguity there: the part of
| the program that "owns" any data object will
| automatically deallocate the object if it's done with it
| and has not transferred ownership elsewhere. This works
| exactly like the usual C++ RAII, but it's generalized to
| the whole language. Even the standard .drop() operation
| follows these semantics.
| joakimds wrote:
| Thanks for clarifying how the dangling pointers may
| arise. Not everyone agrees with me, but these are my
| thoughts/recommendations when using Ada. Which
| thread/task that has ownership of a variable is
| paramount. Whenever one defines a variable it must be
| crystal clear which thread/task that owns it, for example
| has the right the read or write a value to the variable.
| What I recommend is the Actor Model
| (https://en.wikipedia.org/wiki/Actor_model).
| Synchronization between two tasks can either be through
| shared variables or message passing. Last time I checked
| Academia is inconclusive as to what is the best (least
| error-prone) way for threads/tasks to communicate. What
| seems the simplest to me is message passing. 10 years
| ago, first time I heard of the Actor Model and message
| passing is Erlang and it's a language where these ideas
| are fundamental. So a task owns a variable. If another
| task wishes to change the value of that variable it must
| send a message to the owning task and request it to
| change the value. If another task wishes to know the
| value it must ask the owning task what the value is.
| Since the time I heard of Erlang, other languages like
| Rust and the Pony language has picked up on this too.
| Rust has taken this further by making it possible for one
| task to temporarily borrow ownership to another task and
| it is checked by the borrow-checker.
|
| To implement the Actor Model in Ada one puts all
| variables in the body of the tasks that are in the
| application. It makes them not visible from other tasks.
| So what you need to keep in mind when developing is for a
| task to never send an access-to-object type variable to
| another task. If there is a need to do that you need to
| use Ada/SPARK or Rust to get the proper ownership
| checking done. Btw, Codepeer (static code analysis tool
| for Ada) finds race-conditions, has deadlock detection,
| and warns if there are variables that may be read or
| written to by more than one task.
|
| If one sticks to vanilla Ada (not SPARK) one could
| develop an application based on libadalang that parses
| all the Ada source code and checks that all task entries
| have input arguments that do not contain any access-to-
| object types (to find instances where a developer has
| sent an access-to-object variable to another task by
| mistake). Such a tool does not exist but libadalang
| exists to allow the creation of custom rules checking on
| one's Ada code.
| throwaway81523 wrote:
| > I'm confused when people don't use it for bigger
| systems. I like that the compiler detects most of my
| errors before I run the program.
|
| That is more likely due to the type system than manual
| memory management. People after all say the same thing
| about Haskell, which also has powerful types, but is
| garbage collected.
|
| There are two kinds of code errors to worry about: wrong
| answers (2+2=5), and divergence (a fancy name for
| crashing, i.e. 2+2=segmentation fault). In a jet engine
| controller, wrong answers and segfaults both potentially
| cause fatalities, so you better not use GC. Ada is made
| for that.
|
| In (say) a compiler, bugs leading to wrong answers
| (incorrect code emitted) might cause potential
| fatalities, but if the compiler segfaults from running
| out of memory, that's only annoying (the developer must
| find a workaround, use a bigger computer, or whatever).
| So it is fine to write a compiler in a GC'd language even
| if its memory footprint and timing characteristics are
| hard to verify. If you wrote a compiler in Ada you'd
| spend a bunch of time with manual memory management, for
| little benefit.
|
| In fact the most serious formally verified compiler
| (compcert.inria.fr) is written in Coq, which you can
| think of as an ultra precise dialect of OCaml and which
| is GC'd (Coq in this case generates OCaml code that uses
| the OCaml runtime. It can also generate Haskell etc.).
| zetalyrae wrote:
| Having separate module interface and module body files, as in Ada
| or Modula-2/3, is a great idea that sadly a lot of people are
| burnt out on because C and C++ do this in a very unprincipled
| way.
|
| Having a terse little file where I can scan the interface of a
| module, rather than having to scroll through the implementation
| and see which declarations have `public` in front of them, is a
| great way to quickly refresh your mental model of a module's API.
|
| And it allows you to have both interface docstrings and
| implementation docstrings, which a documentation generator could
| use to compile an API guide for clients and a developer's guide
| for people working on the internals.
| MaxBarraclough wrote:
| > Having a terse little file where I can scan the interface of
| a module, rather than having to scroll through the
| implementation and see which declarations have `public` in
| front of them, is a great way to quickly refresh your mental
| model of a module's API.
|
| There's also another structured approach to the
| interface/implementation distinction: leave it up to the IDE to
| offer an interface explorer. This is the approach used by, say,
| Java.
|
| I'm not sure that either approach is outright better than the
| other; it's a trade-off.
| zetalyrae wrote:
| I tend to prefer things being on the code itself as opposed
| to being added dynamically by the IDE. For example I think
| type annotations should be in the IDE.
|
| This is because it lets me read code in extra-IDE settings:
| browing GitHub, or in a patch file, or on a book. Or I can
| write code on paper.
|
| Another benefit is that you can design a program entirely by
| writing the module interface files, and typechecking them
| against each other without an actual module body file.
|
| Then, as you start actually implementing the program, you can
| implement one module at a time, typechecking it against the
| module interfaces of its dependencies, without said
| dependencies having any actual code in them. So you can write
| the actual implementation in whatever order makes sense.
| joppy wrote:
| In C++ you can't really even separate them if you want to
| define templates, because (unless I am mistaken) template
| instantiation can only be done at compile time rather than link
| time. It's sad to not be able to cleanly separate the interface
| from the implementation.
| zetalyrae wrote:
| Yes, I think the module interface file should be for the user
| rather than the compiler.
|
| The compiler would parse both the module interface and module
| body files, merge them and check for consistency, and produce
| both an object code file for the code in that module and a
| binary module interface that contains an efficiently
| serialized form of the interface, the bodies of generic
| functions, and maybe the table of monomorphic instances for
| separate compilation.
|
| Then the build system makes sure to import the relevant
| binary interface files when building a project.
| pjmlp wrote:
| Just like C++20 modules allow.
|
| You only need to export the public parts of the templates.
| pjmlp wrote:
| You can now when using C++20 modules.
| bboreham wrote:
| If my memory isn't failing me, the Sun C++ compiler I used in
| 1994 did template expansion and compilation at link-time.
| However it was rather annoying in use, having to wait a long
| time to get errors arising from instantiation.
| ojeda wrote:
| "Interface files" that are intended as a form of documentation
| should be generated automatically instead.
|
| As for interface vs. implementation docs, nothing precludes
| having both in a single file either.
| mojuba wrote:
| Coming from Pascal/Delphi background I too find the structured
| separation useful (unlike the unstructured one in C/C++),
| though obviously it has a cost of typing the declarations
| twice.
|
| Then for more modern languages where there's no separation some
| IDE's can auto-generate the interface declarations along with
| the associated comments. E.g. Xcode does it for Swift and it's
| kind of OK.
| badsectoracula wrote:
| > though obviously it has a cost of typing the declarations
| twice
|
| In Lazarus you can have the IDE do the syncing for you
| (Ctrl+Shift+C). Modern Delphi might have something similar
| (if not exactly the same thing).
| badsectoracula wrote:
| Free Pascal has units (aka modules) with the interface and
| implementation in the same file but in separate sections, e.g.
| unit Foo; interface type Weekday =
| (Mon, Tue, Wed, Thu, Fri); procedure
| DoThisAt(Day: Weekday); implementation
| procedure DoThisAt(Day: Weekday); begin //
| stuff end; end.
|
| This helps keep things together and up to date (the Lazarus IDE
| can automatically sync the implementation section with the
| interface section, no need to type stuff twice manually) and
| you can still scan the interface section to see its API without
| bothering the implementation section (but it is still just a
| scroll away if you want).
|
| (FWIW this is an old feature taken from Turbo Pascal which
| itself took it from UCSD Pascal)
| masklinn wrote:
| > Having a terse little file where I can scan the interface of
| a module, rather than having to scroll through the
| implementation and see which declarations have `public` in
| front of them, is a great way to quickly refresh your mental
| model of a module's API.
|
| That information is trivial to extract, there is no reason to
| force the developer to maintain it and keep it in sync.
|
| > And it allows you to have both interface docstrings and
| implementation docstrings, which a documentation generator
| could use to compile an API guide for clients and a developer's
| guide for people working on the internals.
|
| You could call these "docstring" and "comment".
| Jtsummers wrote:
| You don't want to extract it. The intention is that the
| specification (the thing you code against, you do write those
| down, right?) is separate from implementation so that you can
| provide _multiple_ implementations.
|
| If you rely on extracting the interface from the
| implementation then you have to have another mechanism to
| compare two implementations to see if they provide the same
| interface. That's kind of an insane way to do things from the
| Ada perspective. You've made things _harder_ for yourself and
| less certain for the users of that interface.
|
| Put the public bits into a package specification file so that
| anyone can know as the user or the implementer what is
| expected. Swap out implementations as needed and have high
| confidence that (short of logic errors in the implementation)
| it will at least provide the same interface because, well, it
| wouldn't compile otherwise.
|
| Also, the specification files are a bit like C or C++
| headers. You can write a program predicated on their
| correctness without actually needing an implementation to
| verify against. The *.ads files tell you "These functions,
| procedures, and types exist. I promise, so you can go about
| your business even though an implementation may not be
| available yet.
| occoder wrote:
| >> Having a terse little file where I can scan the interface
| of a module, rather than having to scroll through the
| implementation and see which declarations have `public` in
| front of them, is a great way to quickly refresh your mental
| model of a module's API.
|
| > That information is trivial to extract, there is no reason
| to force the developer to maintain it and keep it in sync.
|
| That's true, _in theory_. In reality though, when is that
| information extracted? What do you use to extract it? Where
| is it saved once extracted? How easy is it to review it? Do
| you need to use an IDE to do that?
|
| Any less than satisfactory answer to these questions will
| make this worse in practice than having the developer
| maintain it.
| bogeholm wrote:
| > That's true, in theory. In reality though, when is that
| information extracted? What do you use to extract it? Where
| is it saved once extracted? How easy is it to review it? Do
| you need to use an IDE to do that?
|
| You could use your build system to extract it to a website
| (eg. https://docs.rs/)
| gavinray wrote:
| > That's true, in theory. In reality though, when is that
| information extracted? What do you use to extract it? Where
| is it saved once extracted? How easy is it to review it? Do
| you need to use an IDE to do that?
|
| This is part of the GNU Ada toolchain.
|
| I don't write Ada, but I have looked into it. I strongly
| dislike having to write an entire separate type/interface
| file that repeats the type definitions from the
| implementation.
|
| This information exists -- a tool should be able to extract
| the signatures and spit out the interface file
| automatically (IE a header for C/C++)!
|
| In Ada, this tool is called "gnatchop"
|
| https://learn.adacore.com/courses/GNAT_Toolchain_Intro/chap
| t...
|
| Instead of writing an ".ads" and ".adb" file (like ".h" and
| ".c"), you just write an ".ada" file and feed it to
| "gnatchop", it creates the two files for you and you're
| ready to compile. gnatchop example.ada #
| (example.adb + example.ads created) gprbuild p_main #
| (builds from example.adb)
|
| Another neat thing Ada can do is interop with C++! It has C
| interop, but can ALSO support C++.
|
| https://gcc.gnu.org/onlinedocs/gnat_ugn/Interfacing-with-
| C_0...
|
| https://docs.adacore.com/gnat_rm-
| docs/html/gnat_rm/gnat_rm/i...
|
| It can take C/C++ headers and auto-generate the interop
| code you need as well $ g++ -c -fdump-ada-
| spec -C /usr/include/time.h $ gcc -c *.ads
|
| https://gcc.gnu.org/onlinedocs/gnat_ugn/Running-the-
| Binding-...
|
| https://gcc.gnu.org/onlinedocs/gnat_ugn/Generating-
| Bindings-...
| foerbert wrote:
| I can understand your hesitancy, but I think in practice
| I strongly disagree.
|
| A big part of why I like Ada so much is the fact it lets
| me hold such a strong mental model of the program. I can
| specify quite a bit about how it should all work, and the
| compiler holds me to it.
|
| Most or all of that sort of information is tied up in the
| .ads file. If I want to refer to the model, I can check
| the .ads file, even if my project doesn't compile yet.
| Everything I need to know is there, from the very first
| line of code.
|
| Most importantly, if I'm working in the .ads file, I'm
| changing the model. Changes here are Important. If I
| unknowingly make a change here, I've lost my
| understanding of the model. I really don't want that to
| be possible.
|
| Meanwhile the .adb is more the implementation. If I'm
| changing the .adb, I'm just altering the details, but the
| overall model stays the same. Maybe what I'm doing in the
| .adb tells me I really do need to change the .ads because
| the model has a problem, but that doesn't mean I should
| just go make the easiest little change to the model that
| makes the .adb work.
|
| Frankly, I think that extra little bit of friction in
| having two files that need to be in sync makes it easier
| to write better programs. Something as huge as changing
| the model should have _something_ that helps cue me in
| that I 'm doing something Big.
| turbohz wrote:
| The compiler should be able to provide it
| nerdponx wrote:
| I have never used Ada. But I really like the idea of having
| implementation documentation separate from interface
| documentation, and treating it like real documentation with
| its own searchable/linkable HTML or PDF reference document.
|
| A good IDE can then fold/collapse the in-code documentation,
| and the programmer can have it up in a separate window along
| side.
|
| This could be an interesting model for literate programming.
| Instead of it being "linear", like reading a novel, it would
| be like reading a translation of an ancient text, with the
| original source material on one side of the page and both the
| translation and detailed reference notes on the other side.
| And of course there would be a hypertext component to the
| documentation, which would allow you to build a "table of
| contents" and jump around the codebase.
| masklinn wrote:
| > This could be an interesting model for literate
| programming. Instead of it being "linear", like reading a
| novel
|
| It's unclear what you mean by "linear" here. Surely your
| "translation of an ancient text" is a linear read following
| the "ancient text" it translates even if it has forwards
| and backwards references?
|
| Knuth's original conception of literate programming was
| non-linear in terms of code, you'd write some text, write
| some bits of code, possibly add a reference to an other
| snippet, write some more text, write some more bits of
| code, and tangle then stitches the source back together by
| following references.
|
| More "modern" literate programming is non-linear in terms
| of narrative, making the "comments" / "docstrings" the main
| content but then having the code execute "normally"
| ignoring said comments.
|
| Jeremy Ashkenas's tools (e.g. undescore, backbone, ...) are
| all written and published in that style even though
| Javascript is hardly conducive to it, and shown in exactly
| the "original source material on one side and translation
| and detailed notes" you seem to talk about on the other.
| That is what Ashkenas called "annotated source":
| https://backbonejs.org/docs/backbone.html,
| https://underscorejs.org/docs/underscore-esm.html.
|
| Recent revisions of underscore have been modularised and
| show individual segments you can look between instead:
| https://underscorejs.org/docs/modules/index-all.html maybe
| that's what you're thinking of when you talk about it being
| non-linear?
|
| It's missing some of the bits e.g. the symbols themselves
| are not hyperlinked and there is no glossary, but because
| in the modularized version each function is the sole export
| of its module it's easy to jump between functions. Not that
| I'm convinced this makes for a great experience as it
| requires keeping a lot in memory, but there you go.
| nerdponx wrote:
| I meant "linear" as in you start at point A and read
| until point B. That is, pieces of information are
| presented and organized as a sequence of one item after
| another. I am envisioning a system where the programmer
| has code in one window and the explanation of the code in
| another. Like a book with text on the left and
| annotations on the right.
| masklinn wrote:
| > I meant "linear" as in you start at point A and read
| until point B. That is, pieces of information are
| presented and organized as a sequence of one item after
| another.
|
| That is the definition of the word, it's not actually
| helpful in understanding what you're thinking about.
|
| > I am envisioning a system where the programmer has code
| in one window and the explanation of the code in another.
| Like a book with text on the left and annotations on the
| right.
|
| So... literally what i posted.
| nerdponx wrote:
| Doesn't OCaml have something like this too?
| kqr wrote:
| F# does, so I assume OCaml does too.
|
| "Wait F# does?"
|
| Yeah, but you won't have seen it because almost nobody uses
| it to the point where some tooling even has trouble
| understanding what it is. :(
| yawaramin wrote:
| Indeed, and that was inspired by Modula-2 actually:
| https://dev.to/yawaramin/ocaml-interface-files-hero-or-
| menac...
| SavantIdiot wrote:
| Ada is like the exact opposite of "move fast and break things".
| Ada is more like: think long and hard before writing your first
| line of code.
| ksec wrote:
| >think long and hard before writing your first line of code.
|
| Which is no longer allowed in Modern software development
| influenced by Silicon Valley.
| glafa wrote:
| I'm personally amazed by their productivity
|
| - in 4 months of learning the language they've completed 7
| projects
|
| - they've read a 700 page book in a month
|
| - they've made a ebook on ada
| bdavis__ wrote:
| There were a few studies on ada (avionics software) and
| productivity when the language first came out, and ada scored
| very well compared to the state of the art at that time. People
| learned that using static typing and sub-typing moved a lot of
| defects from runtime to compile time. (that was sure my
| experience; getting it to compile took hours, but runtime
| errors were greatly diminished). Looking back, the power of the
| "spec and body", IN and OUT parameters, and such where just so
| much more powerful than Fortran or Assembly or even JOVIAL. C
| was too uncontrolled and wild.
| ggm wrote:
| Well written. Always interesting to see new eyes in modern guise
| on old ideas. I studied and worked at the university of york,
| 1980s, but not on their Ada compiler project. I recall it had an
| astronomical number of passes, and was said to have been formally
| rejected as "not compliant" until they removed a compile time
| warning which said something like:
|
| _congratulations you have used the most obscure part of the ada
| specifications_
| WalterBright wrote:
| I always liked Ada, going back to the first MIL-STD-1815 of it
| (from 1980). It looked very complicated to me at the time, so I
| didn't try implementing it (instead I thought C++ would be a
| couple months to implement and did that instead).
|
| A couple things D took from Ada were the in, out, and inout
| parameters, and embedding _ in numeric literals like 1_000_000.
|
| The latter is _so_ simple and _so_ useful.
|
| I still have my copy of MIL-STD-1815 on the shelf. No, you can't
| have it.
| mst wrote:
| The 1_000_000 thing exists in perl as well (I think also via
| theft from Ada) and frankly I can't understand why _everybody_
| hasn 't stolen it.
| jhayward wrote:
| Pretty much every currently updated language does these days.
| WalterBright wrote:
| This wasn't remotely true in 2000 when D was being created.
| AFAIK D was the first after Ada, and certainly popularized
| it as I made many presentations including it.
|
| C is still holding out :-)
| mst wrote:
| Perl 5.000 was released in 1994 (see
| https://perl.bot/p/kw3gbl for a demonstration that had
| the syntax)
|
| Edit: That bot is far too easy to be curious with, and
| unless I got my testing wrong, perl 2 (from 1988) seems
| to have been where it was added:
| https://perl.bot/p/jzyi91
|
| All assistance convincing the rest of the world they
| should also adopt the feature is very much welcome though
| :D
| rswail wrote:
| Interesting review... the last time I looked at Ada was back in
| the 90s when it was being promoted as the new/replacement C, was
| the "chosen" DOD language etc.
| kqr wrote:
| Most programmers fall into one of two categories in terms of how
| they think about program structure. Either
|
| 1) They think the fundamental elements of code are classes and
| methods on classes, or
|
| 2) They think the fundamental elements of code are functions.
|
| Sometimes either of these also know there's something called a
| module or package, but the idea is loosely understood.
|
| I was one of these people. If you're happy to stay that way, stop
| reading my comment now.
|
| Ada is extremely well designed. One of the reasons is that the
| language design cleanly separates concepts normally bunched
| together into ideas like "everything is a class".
|
| In many languages, if you want implementation hiding you get a
| whole bunch of other things with it. You can't use just
| implementation hiding without automatically opting into all parts
| of class-based programming, like inheritance, subclassing, etc.
|
| Then you go "wait, what? Isn't inheritance and subclassing sort
| of the same thing?"
|
| Yeah, no. Not fundamentally. It's only the same thing in popular
| programming languages because _everything_ is the same thing in
| popular languages. Everything is a class and if you need anything
| you get the whole class concept, whether or not you wanted it.
|
| This is problematic especially for beginner programmers because
| they learn implementation hiding is good. So they use that. But
| that opens up a huge toolbox of additional tools, not all of
| which are appropriate. But beginners are like beginners are, and
| when they see all those tools they simply use them -- sometimes
| out of desperation. This leads to messy code.
|
| Ada is different. In Ada, you can pull out just the concepts you
| need, and it won't automatically opt you in to everything else.
|
| A beginner that uses implementation hiding in Ada won't suddenly
| have an open toolbox full of subclassing. Their toolbox still
| contains just implementation hiding and whatever else they
| intentionally put in it. That leads to better code.
|
| Just for that experience, Ada is worth learning, in my opinion.
|
| Here are some quotes from TFA that alludes to this.
|
| > Packages are namespaces for functions and types, unlike other
| languages where types can "contain" functions and types.
|
| Organising code into subcomponents with implementation hiding is
| separated in Ada from class-based programming. You can do both,
| but you can also choose to do only one of them.
|
| > Function overloading acts as a key design element
|
| You can have polymorphism without opting into inheritance.
| (Further, you can have inheritance without opting into class-
| based programming.)
|
| > Everything in a package is related, there's no syntactical
| split between "free function", "class function", or "member
| function" (method).
|
| You can have methods on types without opting into class-based
| programming.
|
| > What most C-family languages call "functions", Ada calls
| "subprograms". Ada distinguishes between those which return a
| value and are truly "functions" and those which do not return a
| value, and are "procedures."
|
| A procedure is fundamentally different from a function from a
| reasoning-about-the-code perspective. You can have either without
| automatically opting into the other (as is the case when
| everything is a method.)
|
| > Examples are "accesses" (sort of like pointers), "accesibility"
| (similar to a scope for borrowing), "tagged types" (classes),
| "derived types" (unrelated to OOP), and "subprogram".
|
| Using different words for different concepts -- instead of
| bundling them into the same generic idea -- increases the
| richness of your mental vocabulary which also increases the
| nuance your thoughts are able to express.
|
| ----
|
| If you read my comment all the way down here, you might be
| interested in the Rust beginner's tutorial adapted to Ada, one of
| my more popular articles (which tells you something about my
| popularity...) https://two-wrongs.com/guessing-game-ada-
| style.html
| masklinn wrote:
| > A procedure is fundamentally different from a function from a
| reasoning-about-the-code perspective.
|
| They really are not unless the langage puts specific
| limitations or features on one or the other.
|
| And odds are the average "procedure" should not be one, because
| it only exists for its side effect but then provides no
| feedback about these side effects.
| pwr-electronics wrote:
| https://www.adaic.org/resources/add_content/standards/05rat/.
| ..
|
| Interesting history of how there was supposed to be a
| difference, but the idea was dropped and then later revived
| by SPARK.
| masklinn wrote:
| GP is not talking solely about ADA though, they are
| asserting that there is a fundamental difference which is
| embodied solely in the presence or absence of a return
| value which is missing from e.g. "everything is a method"
|
| Differentiating between pure and impure functions _might_
| be useful[0], but while not strictly orthogonal the
| presence of a return value doesn 't tell you anything about
| that. Even ignoring the error signalling, read(2) has a
| return value (the data being read) and also has side-
| effects.
|
| [0] though it's debatable that this distinction is _really_
| useful in and of itself
| pwr-electronics wrote:
| The general discussion is about Ada ...
|
| GP said it depends on what the language does with that
| concept, and then I linked some extra info about what Ada
| and SPARK do with the concept.
|
| As for whether it's useful ... it's absolutely useful.
|
| Side effects break basic blocks. The smaller the basic
| blocks, the less optimization can be done.
|
| Side effects also require special handling when using
| theorem provers. If you can specify that something should
| be free of side-effects, it's less work to requalify the
| system after making changes.
|
| The purpose of SPARK is to be formally proven, which is
| why it implements the feature.
| kqr wrote:
| Obviously what you're saying is completely correct.
|
| Maybe we can agree on that they _should_ be different, but in
| languages where all code is a method it is dangerous to
| assume they are different?
| masklinn wrote:
| > Maybe we can agree on that they should be different
|
| Why would we? And how should they be different, and what
| useful properties would that provide?
|
| > in languages where all code is a method it is dangerous
| to assume they are different?
|
| Why would you assume undifferentiated functions are
| different in the first place, and what would the difference
| be?
| louthy wrote:
| > Why would we? And how should they be different, and
| what useful properties would that provide?
|
| Functions _should_ be similar to mathematical functions
| and come with guarantees like purity, referential
| transparency, and totality.
|
| Another reason they should be different is they've got
| different names! Might seem trite to say that, but what's
| the point in having the same concept with different
| titles?
|
| Pure functions are very powerful concepts, especially
| when it comes to composition, if the consumer of a
| function can't rely on that, then the consumer must
| investigate the internals to know what it does. Once
| you're several layers deep into your composition that
| becomes exponentially harder to do.
|
| So, there is value to having a concept (with a suitable
| name, like 'function') that indicates to the consumer
| what it is they're dealing with. Some languages, like
| Haskell, bake this in; others like JS really don't -
| making the whole process of dealing with 'functions'
| (really procedures) much harder once an application is
| more than a toy project.
| masklinn wrote:
| > Functions should be similar to mathematical functions
| and come with guarantees like purity, referential
| transparency, and totality.
|
| Essentially none of that is embodied in Ada's distinction
| between functions and procedures though, despite that
| being "fundamentally different [...] from a reasoning-
| about-the-code perspective" according to the comment I
| replied to.
|
| The only thing Ada tells you is "this definitely has
| side-effects" because there's no other reason to have a
| function without a return value, but that's the least
| useful thing you can be made aware of.
|
| > Another reason they should be different is they've got
| different names! Might seem trite to say that, but what's
| the point in having the same concept with different
| titles?
|
| Because you're very confused and making a distinction
| between things which are not different?
|
| > Pure functions are very powerful concepts
|
| That's debatable, but even then _it 's not what function
| means in Ada_.
|
| > especially when it comes to composition, if the
| consumer of a function can't rely on that, then the
| consumer must investigate the internals to know what it
| does.
|
| Knowing what a function does is probably a good idea
| either way. You can call `map` with the same parameters
| as `filter` but the result will be rather different.
| adrian_b wrote:
| Initially, Ada had the restriction that the functions
| must be pure.
|
| The restriction has been lifted only much later, so what
| you say is correct for modern Ada, not for the original
| Ada.
|
| While gcc and other C and C++ compilers have non-standard
| extensions to specify whether a function is pure or not,
| I assume that an Ada compiler can recognize a pure
| function just by the fact that all its parameters are
| "in", so no extra keyword is needed.
|
| What is needed is that the pure functions must be easily
| recognized by compilers and other tools and also by
| programmers. Not only there is no need that the functions
| be restricted to pure functions, that is actually
| undesirable.
|
| AFAIK, unlike in C/C++, where pointers can make this task
| quite complex, in modern Ada it is still easy to
| recognize the pure functions.
| adrian_b wrote:
| The more common distinction between functions that return
| values and procedures that do not return values is not
| important at all.
|
| On the other hand the distinction between "pure functions"
| and other kinds of functions or procedures is quite
| important.
|
| In many early programming languages, the "functions" had to
| be what now are called "pure functions".
|
| Later many languages relaxed the restrictions for
| "functions" allowing them to have side effects, but then
| the more important distinction was lost.
|
| Only relatively recently many languages began to provide
| again means to specify that a function is a pure function.
| scns wrote:
| As a pedant myself, i find this rather pedantic. Language
| use evolves and insisting it is only correct when words
| are used with their original meaning won't win you much.
| If you distinguish between produres and functions or
| functions and effects, many will get what you mean and it
| is more elegant IMSubjectiveO.
|
| Same goes for im/mutability, i think val/var is more
| elegant than let/let mut but that is only my opinion on
| aesthetics. I like good design but still think function
| is more important than form.
| adrian_b wrote:
| The "pure" functions have different properties with
| respect to program optimization and program verification,
| in comparison with the functions or procedures with side
| effects.
|
| That is the reason why this distinction matters. The
| distinction between mutable and immutable variables
| matters for the same reason.
|
| Otherwise, the difference between a "procedure" and a
| "function" with side effects where you ignore the return
| value has no practical consequences.
|
| There are contexts where you do not care about the
| optimizations that can be done by the compiler or about
| program verification, but there are also contexts where
| you care.
| thindil wrote:
| 1. In the older versions of Ada standard, functions can't
| have side effects, in a sense that they are not allowed to
| return more than one value (by setting the function's
| parameter's mode to out). Procedures always allowed to have
| side effects.
|
| 2. Functions can be expression functions which can be set in
| the code specification or used in expressions. Procedures can
| be written only in packages' bodies.
|
| 3. Procedures can be set to no-return state: that kind of
| procedure doesn't end in the normal way, but, for example,
| only by raising an exception.
|
| 4. Procedures can be null procedures, empty. That not the
| same as abstract subprograms from other programming
| languages.
|
| Also, the difference is, in my opinion, more visible in the
| safe subset of Ada, SPARK, where still exists the rule which
| forbids side effects on functions.
| noisy_boy wrote:
| If you have ever written in Oracle's PL/SQL[0], Ada will come
| across strangely familiar to you (because the designers of PL/SQL
| modelled its syntax on that of Ada). For me, it was almost like a
| blast from the past since I wrote lots of PL/SQL almost 20 years
| ago.
|
| [0]: https://en.wikipedia.org/wiki/PL/SQL
| hnlmorg wrote:
| The similarities are only skin deep though. It's like comparing
| Javascript to Go because they both have C-style braces. Plus
| PL/SQL is an abomination of a language whereas Ada can be a
| real pleasure.
|
| A much closer comparison would be Pascal. Which is another
| awesome language (I was gutted when the home computing industry
| moved away from Pascal and towards C).
| noir_lord wrote:
| > Pascal and towards C
|
| As was I, Object Pascal was for it's time one of my all time
| favourite languages - it was so effortlessly boring it just
| got out the way.
| EamonnMR wrote:
| What is it about SQL embedded languages that made them so
| hard to get right? I had to port a stored procedure from
| MySQL to Pl/PSQL once and it was nuts how much better the
| PSQL one was once it was finished.
| ako wrote:
| What makes pl/sql an abomination of a language?
| slotrans wrote:
| It's not. I wrote a lot of PL/SQL at my first real software
| job and I miss it dearly. I treasure every opportunity I
| get to write a little PL/pgSQL, which is very similar. Use
| it for the right purposes and it's a joy to write.
|
| There are certainly things it can't do, and things it can
| do but only poorly, but that's true of anything.
| hnlmorg wrote:
| It's an attempt at bringing procedural workflows to SQL but
| the two paradigms aren't really compatible. It's much
| easier working with a scripting language like Perl or
| Python and embedding SQL queries. Use a relational language
| for the relational logic and a procedural language for the
| procedural logic.
| noisy_boy wrote:
| Granted PL/SQL isn't as flexible as Perl or Python - it
| is not a fully-fledged application/system language (don't
| think it was meant to be that). Having said that, it does
| have ability to define types/reference column/row types,
| typical data structures like arrays/hashes/records(which
| are like structs), control-flow etc but the main point is
| that all of that runs within the database engine - this
| is useful when you must deal with complicated conditional
| logic but don't want to make those round-trips and handle
| all of it in one go. Generally traditional relational SQL
| is the preferred approach and it can cater to conditional
| scenarios as well but sometimes SQL statements combined
| with conditional logic written procedurally in one place
| is simpler to understand/more performant.
|
| To be clear, I'm not advocating this over the traditional
| approach of programs running discrete queries and
| handling the logic themselves - just saying that the
| approach taken by PL/SQL has its merits.
| hnlmorg wrote:
| I get the reason for PL/SQL and completely understand the
| advantages of stored procedures (I used to write code for
| Oracle Middleware so have had several years of experience
| in specifically this domain). I'm just answering the
| question of why the language sucks to write code for.
|
| I'm not suggesting PL/SQL should be a fully fledged
| scripting language either (neither Perl nor Python are
| systems languages by the way). I'm just saying the two
| paradigms PL/SQL aims to leverage don't combine well so
| the end result is always going to be ugly.
| masklinn wrote:
| > Granted PL/SQL isn't as flexible as Perl or Python
|
| Which, incidentally, can be used as procedural languages
| in Postgres (as well as TCL) as part of the standard
| distribution.
|
| And there are third-party extensions for javascript,
| ruby, scheme, r, java, lua, ... (though some of them may
| not be maintained anymore, the pg13 documentation doesn't
| list scheme and ruby anymore).
| edem wrote:
| I came here to read about Cardano, then I realized that this was
| about the programming language.
| edem wrote:
| Why all the hate?
| yawaramin wrote:
| Because it's an irrelevant comment. If the topic is not what
| you expected, keep scrolling. No need to let everyone know.
| greg7mdp wrote:
| Both are named after Ada Lovelace, mathematician and first
| computer programmer.
| eashish93 wrote:
| Same thought. I think the article on top because of ADA coin.
| DonHopkins wrote:
| I hoped it was about Ian Dury and the Blockheads.
|
| https://www.youtube.com/watch?v=8EMR9DXU_NQ
| jl2718 wrote:
| I went to a college that taught CS in ADA, and I never took CS
| because I tested out of 101, but I ended up fixing attempts at
| the problem sets for about half my dorm section (this was okay as
| long as and they documented it).
|
| Well anyway, I found it to be very easy to pick up just by
| reading, hard to make semantic errors, and easy to modify without
| breaking things. The pace of learning for the entire cohort,
| mostly non-CS students, was, I think, much faster than e.g. C++
| and possibly more complete than e.g. Python. It's pedantic and
| exact, but it uses real english language keywords and modifiers.
|
| I went to a different school later where I did the same thing but
| it was taught in C++. It seemed like many students would get by
| purely by repeating patterns that they didn't understand. And I
| started to catch myself in that trap as well, realizing that I
| had a lot to learn.
|
| But I wasn't going to be a programmer; I was going to be a
| theoretical physicist cogitating on the deep mysteries of the
| universe. Fast forward.... D'ohhhh.
| zozbot234 wrote:
| Does "real english language keywords" actually make it easier
| to learn programming? AIUI, this was popular in the past simply
| because many computing systems used bespoke, pre-ASCII
| character sets, sometimes with few symbols available and no
| distinction between uppercase and lowercase (hence why Ada is
| case insensitive as well!). Typing stuff like DIVIDE A INTO X
| can come in handy when your machine literally doesn't have a /
| character.
| SkyMarshal wrote:
| Ada intentionally prioritizes readability over write-ability,
| hence English-language keywords and the like. It's designed
| for large, long-running systems that must be maintained over
| years or decades.
|
| The thinking is that over their lifetime, such systems will
| be read more than written, by rotating teams of programmers
| who need to get up to speed with a complex codebase,
| repeatedly. In maintenance mode, modifications will be less
| frequent than reads.
| zozbot234 wrote:
| "Real English language keywords" for readability was
| probably the most sensible choice back in the early 1980s
| when Ada was first standardized. They're rather less
| popular today, of course. The interesting question is, does
| using, e.g. BEGIN and END instead of curly brackets really
| make it easier for novices who are learning to code today.
| It's an interesting topic and one that isn't often seen
| here.
| foerbert wrote:
| "begin" and "end" are probably the most arguable, but in
| the context of everything else being a real-word keyword
| I think they make sense.
|
| Ada was not my first language, and I was a little dubious
| about the keywords at first, but I quickly changed my
| mind. Now I wish every language did it (obviously, not
| literally every). It's really nice for a couple reasons.
|
| One is just googling. You pretty much have a built-in
| shared lexicon, so there's no trying to remember the
| right name for the problematic symbol, or figuring out
| the best way to describe it.
|
| There's also no trying to remember what symbol does the
| thing you want, which is really nice even when just
| coming back to a language feature you haven't used
| recently enough to be fresh on.
|
| I have no idea how much these things would matter in a
| more structured environment. I pick up words way faster
| than symbols and my memory isn't so great, so I think it
| would have helped me even there. But I don't know how
| universal that is.
|
| Though given the number of times I had to help the actual
| CS majors with basic syntax stuff, even after the 101
| course... I can't help but suspect it would be useful.
| formerly_proven wrote:
| Pretty sure it does. Line-noise languages (e.g. math, C++,
| Rust, Perl, K) optimize for expert use, the trade-off being
| that they're difficult to parse and understand for newcomers
| and infrequent users. There is of course also a huge
| difference between languages were the meaning of
| symbols/notation is largely context-independent (e.g. the
| three types of braces in C) and those were this is not the
| case (e.g. C++, math).
| tialaramex wrote:
| I agree C++ is worse about the context dependence than C
| but they're both pretty bad about this. Notice that C has
| two _different_ operators named * and two named & for
| example.
| mst wrote:
| perl: there's more than one way to obfuscate it C:
| there's more than one way to segfault it
| mst wrote:
| _looks at vote count_
|
| I see I have enraged the C programmers.
|
| My apologies for being terrible at C memory management,
| though in my defense I am sufficiently self aware of this
| to realise that means it's safer for me to stick to perl
| as a weapon of choice.
| kqr wrote:
| I think science is divided on this question. There's that one
| study showing that many languages with C-like syntax are as
| easy to learn to read as languages with tokens picked
| completely at random[1].
|
| But that talks about learning the language. What about once
| you're proficient?
|
| I vaguely remember reading about a study that concluded more
| terse symbol-based syntax is better because the programmer
| can use visual organisation of the code to greater extent
| because the syntax occupies less of the screen. But I could
| also be making it up because I can't find it now.
|
| There's also the interesting (but slightly irrelevant) result
| that abbreviated identifier names may be just as effective as
| ones spelled out![2]
|
| [1]: https://dl.acm.org/doi/abs/10.1145/2534973
|
| [2]:
| https://link.springer.com/article/10.1007/s11334-007-0031-2
| ajxs wrote:
| Great article! I've written lots of Ada, and I actually had no
| idea Ada had such a thing as _" Expression functions"_. I do
| understand the reasons why many people seem to dislike Ada so
| much, compared to C it's fussy and verbose. However using Ada
| resolves so many of the issues people have with coding in C, and
| C++. I'd recommend anyone who regularly writes programs in C to
| see what Ada has to offer. SPARK is also worth taking a look at.
| AdaCore's documentation on what SPARK has to offer to people
| working with MISRA C makes a great case for the language's use:
| https://learn.adacore.com/courses/SPARK_for_the_MISRA_C_Deve...
| thesuperbigfrog wrote:
| >> I actually had no idea Ada had such a thing as "Expression
| functions".
|
| The John Barnes book mentioned in the article covers some of
| the differences between the Ada language versions.
|
| Expression functions were added in Ada 2012 and directly
| support preconditions, postconditions, and various aspects in
| SPARK 2014.
| TurboHaskal wrote:
| > "There's some quirky behavior, like tab indenting to where it
| thinks the indent should be and not actually inserting a tab."
|
| No sorry, inserting a tab is the actual quirky behavior.
| systems_glitch wrote:
| ZERO-NINE! Good to see you're still hacking on stuff :)
| pyjarrett wrote:
| That's a very welcome blast from the past! :)
|
| Feel free to send an email if you want to catch up.
| systems_glitch wrote:
| Sent to your gmail!
| guerby wrote:
| Interestin things about Ada:
|
| - language designer have a document where they explain their
| choices, the Ada Rationale: http://www.ada-
| auth.org/standards/rationale12.html
|
| - there is an annotated version of the standard, and it's freely
| available as the standard: http://www.ada-auth.org/arm.html
|
| - A language test suite was developped at the same time of the
| language:
| https://en.wikipedia.org/wiki/Ada_Conformity_Assessment_Test...
|
| The last point was also in retrospect not sot good for the
| language ecosystem: buyers wanted a 100% on this test suite
| before considering your Ada compiler, which means dev had
| hundreds of compiler bugs to fix and no paying customers.
| zetalyrae wrote:
| I think every language should have a design rationale. I'm
| working on the spec for my programming language, and I intend
| the rationale to be >50% of the size of the spec. It's great
| because it allows me to justify every facet of the language as
| part of a cohesive whole.
| ghoward wrote:
| I think this is a good idea.
|
| I'm also designing a language, and I have the rationale sort
| of written, but scattered amongst many design documents. I
| should put it all in one place like you.
| mike_hock wrote:
| > The last point was also in retrospect not sot good for the
| language ecosystem: buyers wanted a 100% on this test suite
| before considering your Ada compiler, which means dev had
| hundreds of compiler bugs to fix and no paying customers.
|
| You mean, they couldn't sell a half-finished product while
| claiming "100% conformity"? Awesome.
| guerby wrote:
| Compiler validation is done by a third party so you cannot
| claim validation without really passing the testsuite.
|
| All compilers have bugs and releases happen (at least for GCC
| which I know a bit more than others) with plenty of known
| open bugs.
|
| Having a testsuite is of course a good thing, however if you
| take the top 20 programming languages in use, how many of
| them do have an accepted wide coverage publically available
| language test suite?
|
| You said "half-finished product" but what about compiler for
| every other language than Ada of which most of them don't
| have a testsuite? How do buyer decide to use Intel C Compiler
| for example?
|
| Remember all of this was in early 1980.
|
| Having this testsuite was well ahead of its time as many
| things with Ada, what I'm trying to say is that it didn't
| play well at the time to help the language ecosystem grow.
| noir_lord wrote:
| Especially given the markets Ada was used in.
| mcguire wrote:
| And it never caught on outside limited contexts because dev
| environments were thousands of dollars per seat.
| ChrisMarshallNY wrote:
| _> dev had hundreds of compiler bugs to fix and no paying
| customers._
|
| From what I understand, a principal rationale of Ada, was to
| have a "100% reliable" toolchain, and compile-time assurance.
| So this is actually a reasonable posture.
|
| It seems that Ada can be challenging. In the 1980s, there was a
| project to rewrite the nation's air traffic control system, in
| Ada (I knew a couple of engineers, working on it).
|
| I don't think it ended well.
| retrac wrote:
| Canada's national air traffic control system is implemented
| in ~1 million lines of almost pure Ada, handling everything
| from the radars to the user interface.
|
| If non-C-family isn't a dealbreaker I would seriously
| consider Ada for a large project. Very strong typing and
| modularity that are very suited for large-scale development,
| a wide range of available toolchains, but without the kitchen
| sink. (But I'm not qualified to make such decisions.)
|
| Besides, something like implementation language is almost
| never why a very large software project fails. (Though if
| you're already failing, then e.g. implementing your cloud
| service in COBOL is probably not helping.) It's usually from
| mismanagement, or a failure to define or understand the
| problem appropriately.
| topdancing wrote:
| > I don't think it ended well.
|
| https://www2.seas.gwu.edu/~mfeldman/ada-project-summary.html
| would suggest otherwise
| ChrisMarshallNY wrote:
| The US version flamed out, in spectacular fashion.
|
| The European one, however, worked.
|
| Another poster put up links ([0], [1]).
|
| [0] https://web.archive.org/web/20160601100527/http://www.b
| loomb... (Unpaywalled)
|
| [1] https://www.skybrary.aero/index.php/Central_Flow_Manage
| ment_...
|
| It wasn't a ding at Ada. However, big projects (regardless
| of the toolset) need to be well-managed.
| egberts1 wrote:
| Sure wasn't a ding against Ada.
|
| It appeared that mismanagement and misprioritization of
| the huge ATC wish list and a failure of system
| engineering to factor limited system resources ... then
| to its priority list.
|
| A different US contractor (that I can't recall)
| apparently did ATC better and faster but for a set of
| different customers (also in Ada).
|
| It must have been when "you don't get fire for hiring
| IBM" was a mantra then.
| Spooky23 wrote:
| I hate to defend IBM, but they did have a track record of
| building out massive systems like this.
|
| I'd guess the 80s political climate and more general
| incompetence at the agency and political level was a
| bigger issue than the vendors and integrators.
| sparcpile wrote:
| The program's name was AAS, the Advanced Automation
| System. It was designed to be a full end-to-end system
| replacement for the HOST mainframe systems that were the
| FAA's backbone. This included terminal, en-route,
| oceanic, and every other system that was managing
| aircraft. AAS is discussed as a failure because it had
| significant mission and requirements creep. FAA kept on
| piling on requirements and IBM kept saying yes.
|
| The FAA also had issues managing it because it was so
| large. It was a multi-billion program with millions of
| SLOC in the early 90s. Simply put, this was a not a cat
| video website. The tool suite was on AIX 3.2.5 running on
| RS/6000s using CMVC for source code management.
|
| This was all designed in the mid-80s with implementation
| starting in the late 80s through the mid 90s. AAS was
| originally designed after the mass firings of the ATC
| specialists and the shutdown of PATCO, the original ATC
| union. AAS was actually a entire suite of programs. AAS
| was overall program and funding vehicle. IBM Federal
| deployed a few of the sub-programs like ISSS, TCCC, and
| others successfully to the FAA.
|
| It was originally developed by IBM Federal Systems and
| deployed on then-new RS/6000s. AAS failed because of
| mission creep and the fact it was entirely too large. The
| program ended after IBM Federal Systems was sold off to
| Loral and then merged into Lockheed Martin. The head of
| the ATC group at the time, Bob Stevens, discovered that
| LM would make more money if FAA cancelled the project and
| split it up into much smaller programs. Bob called up the
| FAA Administrator and made the deal to cancel the program
| since the scope creep was too much. FAA had already sent
| out a couple of cure letters to get things back on track,
| but this time the FAA agreed that it was time to cut bait
| on it.
|
| Initially, what was the en-route portion of AAS was re-
| done as the Display System Replacement (DSR), which
| replaced the radar and data positions in the en-route
| facilities. The concepts of AAS were then rolled into
| NextGen, which is the FAA's family of programs to
| modernize its ATC systems.
|
| Ada was used (originally OC Systems's Ada83 and Ada95
| PowerAda compilers) for everything in AAS. An Ada-based
| middleware called FlightDeck was developed to implement
| all the underlying libraries and subsystems that you need
| for highly available applications for AAS, including
| clustering, failover, heartbeats, monotonic time, and
| multiple levels of redundancy. That middleware is still
| being today for the systems that IBM Federal, Lockheed
| Martin, and now Leidos are maintaining and developing
| like ERAM. After LM bought out what was IBM Federal, they
| sold it off in 2015 to Leidos because LM wanted to focus
| more on hardware.
|
| (Source: I work on the later programs that Ada is used on
| and listened to all stories that were told me by the
| people who worked on AAS).
| synack wrote:
| That ATC project failed for many reasons, mostly
| mismanagement.
|
| Flying In Place: The FAA's Air Control Fiasco
| https://www.bloomberg.com/news/articles/1993-04-25/flying-
| in...
|
| Meanwhile in Europe, Eurocontrol's CFMU (Central Flow
| Management Unit) is written in Ada and successfully routes
| thousands of flights a day.
| touisteur wrote:
| And I'd say out of the US the majority of ATC radars after
| 95 are probably running some mix of Ada and C.
| throw0101a wrote:
| > _Meanwhile in Europe, Eurocontrol ' s CFMU (Central Flow
| Management Unit) is written in Ada and successfully routes
| thousands of flights a day._
|
| Was this a new system, or a replacement of old code? If the
| latter, could that have been a complicating factor?
| niea_11 wrote:
| If anyone is interested, here is "an experience report"
| (slides) about the use of Ada in Eurocontrol' s CFMU :
| https://slideplayer.com/slide/11313411/
| todd8 wrote:
| The concluding slide from this report:
|
| > The Ada language is one of the factors which has helped
| to build, maintain and enhance the CFMU mission critical
| sophisticated applications.
| surfsvammel wrote:
| Ads was one of the languages used to learn basic concepts of
| programming at the university programme I attended. We Lisp and
| Ada where the two main language that we used, to contrast the
| differences.
| alex_duf wrote:
| You wouldn't have trained at the Computer Science University of
| Bayonne (France) would you?
|
| Because we also used Ada as our first language there.
| Tomte wrote:
| University of Stuttgart, as well.
|
| One of the language designers was the department head for
| programming languages and compiler construction.
| tcard wrote:
| Universidad Politecnica de Madrid, too.
| dagw wrote:
| Chalmers University in Sweden used Ada as its intro language
| for a while as well (late 90s).
| toolslive wrote:
| KULeuven (Belgium) used Ada in the mid 90s for some of the
| programming-in- the-large CS courses. (So not as first
| programming language. That was Scheme or Pascal). It (Ada)
| got replaced by Java later.
| tialaramex wrote:
| I learned SML. At the time the CS department here had the
| philosophy that the introductory programming course should be
| in a language students were very unlikely to already know, thus
| putting the self-taught programmers on a somewhat level playing
| field with those who've never programmed a computer before.
|
| They did have to stream that intro course anyway, because
| irrespective of familiar syntax some people "get it" and some
| don't. I remember the bottom stream were named "Strugglers" but
| I don't remember what the stream for people it comes as second
| nature to is called, most people move up and down a bunch e.g.
| maybe they were fine right up until currying, and they go all
| the way from "Attend one lecture a week, complete the assigned
| work in ten minutes, hand in and we're done" to "I need both
| classes and the extra one-on-one tutorial to even understand
| the assignment, let alone try to do it" overnight.
|
| Today I believe they teach Java, or possibly Python, bowing to
| industry pressure to churn out people who can cut code on day
| one, as if that's the purpose of a three year degree.
| Interestingly the same university's IT department just hired me
| based on the rationale that although I don't actually know most
| of the technologies they're using, I clearly can just acquire
| everything needed as I go. So _they_ don 't believe this
| bullshit, but many people hiring their graduates do, and 18
| year olds pick institutions with the best hiring rates.
| chris_wot wrote:
| The link to the tutorial site gives a 404 error
| pyjarrett wrote:
| Thanks for mentioning this. Fixed.
___________________________________________________________________
(page generated 2021-08-29 23:02 UTC)