Hacker Newsnew | past | comments | ask | show | jobs | submit | supplementation's commentslogin

> Ever since then I have not been able to figure out why it is commonly taught next to the variable name.

C does this very cute (read: horrifyingly unintuitive) thing where the type reads how it's used. So "char ⋆a" is written so because "⋆a" is a "char", i.e. pointer declarations mimic dereferencing, and similarly, function pointer declarations mimic function application, and array declarations mimic indexing into the array.


I found it much easier to understand than Pascal. It just clicked. Later there was a moment of confusion with "char* a, b".

It helped than I've learned by K&R C book. Windows API and code examples are horrific, like another language.

https://docs.microsoft.com/en-us/windows/win32/learnwin32/wi...

https://docs.microsoft.com/en-us/windows/win32/learnwin32/ma...


Sorry, can you elaborate? I'm skimming through the documentation and I can't find a section on having "the storage type determined at compile time", except for the section on arbitrary-range integers.


Ada's type system allows you to separate the high-level specification of a type (which models a problem) and its low-level representation (size, alignment, bit/byte order, etc.). The language also requires explicit conversions for two different types even if their underlying representation on the hardware is the same.

Example 1:

   type Byte_Count is range 1 .. 4
     with Static_Predicate => Byte_Count in 1 | 2 | 4;  -- Aspects are Ada 2012

   type Component_Count is range 1 .. 4;

   V1 : Byte_Count      := 3;   --  compiler error: expression fails predicate check
   V2 : Component_Count := V1;  --  compiler error: requires explicit conversion
For these two types I'm not really concerned about how they are represented by the hardware, but I could if I needed to.

Example 2:

Extra constraints added to some pre-defined types:

   subtype String8 is String
     with Dynamic_Predicate => String8'Length <= 8;

   subtype Even_Integer is Integer
     with Dynamic_Predicate => Even_Integer mod 2 = 0,
          Predicate_Failure => "Even_Integer must be a multiple of 2";
Example 3:

Use big-endian for some network packets:

   type Packet_Type is record
      Header : Header_Type;
      Data   : Data_Type;
   end record;
Low-level representation (placed in the private part of a package spec):

   for Packet_Type use record
      Header at 0 range   0 .. 255;
      Data   at 0 range 256 .. 1855;
   end record;

   for Packet_Type'Bit_Order use System.High_Order_First;
   for Packet_Type'Scalar_Storage_Order use System.High_Order_First;
   for Packet_Type'Size use 232 * System.Storage_Unit;


Ada allows you to customize the size and memory representation of a lot of type. It's called representation clauses [1]. It can be very useful if you want to exchange data structures with a different language without marshalling. I have used it to interopt with C++. It can be quite nice and we had some very unpleasant packing bugs in the C++ code which were caught thanks to Ada good error messages.

Overall, working with Ada was quite pleasant. The type system is nice. The module system is nice. Writing concurrent code was really nice. The Algol like syntax somewhat reminded me of my day working in Ocaml. I did miss true variant types however.

[1] https://docs.adacore.com/gnat_rm-docs/html/gnat_rm/gnat_rm/r...


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: