Re: Strong typing and physical units

2020-07-28 Thread Paolo Invernizzi via Digitalmars-d-learn

On Tuesday, 28 July 2020 at 11:04:00 UTC, Cecil Ward wrote:
Of course, in C I used to do something like strong typing with 
an opaque type achieved by using something like typedef struct 
_something {} * type1; and then I had to do casting to get back 
the real type, which was unchecked but it did prevent the user 
from mixing up the types type1 and type2 say as they weren’t 
assignment compatible.


I would really like strong typing to be a built in feature. 
Would anyone else support this?


Once upon a time, typedef was present and backed by the compiler, 
but nowadays you can find it in Phobos [1], but with some quirk 
...


[1] https://dlang.org/phobos/std_typecons.html#.Typedef



Re: Strong typing and physical units

2020-07-28 Thread Cecil Ward via Digitalmars-d-learn
I just remembered: another favourite bug of mine would be mixing 
up indices, using an index with the wrong array, an index to a 
different array entirely. they’re all just a nightmare load of 
meaningless ints or uints or hopefully size_t’s.


Re: Strong typing and physical units

2020-07-28 Thread Cecil Ward via Digitalmars-d-learn
Of course, in C I used to do something like strong typing with an 
opaque type achieved by using something like typedef struct 
_something {} * type1; and then I had to do casting to get back 
the real type, which was unchecked but it did prevent the user 
from mixing up the types type1 and type2 say as they weren’t 
assignment compatible.


I would really like strong typing to be a built in feature. Would 
anyone else support this?


Re: Strong typing and physical units

2020-07-28 Thread Cecil Ward via Digitalmars-d-learn
On Tuesday, 28 July 2020 at 07:16:53 UTC, Petar Kirov 
[ZombineDev] wrote:

On Tuesday, 28 July 2020 at 04:40:33 UTC, Cecil Ward wrote:

[snip]


By the way, I found 2 implementations of unit of measurement in 
D:

https://code.dlang.org/packages/units-d
https://code.dlang.org/packages/quantities


Thank you Peter! Very helpful.

Do you guys have any thoughts also about the strong typing idea?


Re: Strong typing and physical units

2020-07-28 Thread Petar via Digitalmars-d-learn

On Tuesday, 28 July 2020 at 04:40:33 UTC, Cecil Ward wrote:

[snip]


By the way, I found 2 implementations of unit of measurement in D:
https://code.dlang.org/packages/units-d
https://code.dlang.org/packages/quantities


Re: Strong typing and physical units

2020-07-28 Thread WebFreak001 via Digitalmars-d-learn

On Tuesday, 28 July 2020 at 04:40:33 UTC, Cecil Ward wrote:
I found an earlier post somewhere about work someone has done 
on physical units such as kg, volts and so forth.


It would be very good to catch bugs such as

volts_t v = input_current;

[...]


This is easily done and uses enums: (officially defined in the 
specification, not even a hack!)


enum DisplayUnit : int { init = 0 }
enum Width : DisplayUnit { init = DisplayUnit.init }
enum Height : DisplayUnit { init = DisplayUnit.init }

void foo()
{
Width width = cast(Width)16;
Height height = cast(Height)9;

//width = height; // illegal implicit conversion
//width = 4; // illegal implicit conversion
width = cast(Width)height; // legal, force conversion

DisplayUnit val = width; // allowed implicit conversion, 
Width "inherits" DisplayUnit
int num = width; // also allowed, Width "inherits" 
DisplayUnit which "inherits" int


writeln(num); // 9
writeln(width); // cast(Width)9
}

You can then also make helper functions for prettier syntax, see 
https://run.dlang.io/is/X4BA32


But that isn’t nearly enough. With strong typing where we can 
create arbitrary subtypes that are chosen to be incompatible 
because they are semantically incompatible in assignment, 
equality, addition and various other operations, we can catch a 
lot more bugs.


Sadly width += height (and probably all operators other than 
assignment) are still allowed.


However for return codes this makes great sense: it implicitly 
converts down to integers if the user wishes to lose type 
information and otherwise prevents assigning or calling wrong 
functions like some example `enum Win32Error : int` could not be 
used to call a `validate(PosixError)` function


This is also great for opaque handles like for making file 
descriptors type-safe: `enum File : int`, `enum Socket : int` 
which you can't accidentally pass to type-safe APIs but can still 
easily use in C APIs using ints or raw file descriptor access. 
All your wrapper functions simply cast the internal C API return 
values to these type-safe enum types based on context they know.


For other values representing something it doesn't work as great 
as you need to have a helper function to construct them or always 
cast them as well as to!string (and writeln) don't print the raw 
value but rather prepend a "cast(T)" in the string, but it still 
works and is possible.