digitalmars.D - Troubles with user defined subtypes
- bearophile (66/66) Dec 17 2012 Regarding the recent discussions on SafeInts and HalfFloats, I
Regarding the recent discussions on SafeInts and HalfFloats, I find some difficulties in using user-defined sub-range of a type. Let's say I want to define a new type as subset of all the chars, that contains only the digits. This is a very common need in my programs, I often want integral values that are allowed to be only a subrange (or subset, if they are sparse) of a built-in integral type. (In Ada language there is syntax and semantics in the type system to make this easy, safe and nice). Here I have shown some general problems associated with the creation and use of user-defined subtypes: http://forum.dlang.org/thread/jhkbsghxjmdrxoxaevzm forum.dlang.org#post-jhkbsghxjmdrxoxaevzm:40forum.dlang.org This program shows two problems that make subtyping much less handy/useful for me in D: // Start program ------------------------------- struct Digit { immutable char d; this(in char d_) pure nothrow in { assert(d_ >= '0' && d_ <= '9'); } body { this.d = d_; } alias d this; } U[] _validator(U, T)(in T items) pure nothrow { typeof(return) result; foreach (immutable d; items) result ~= U(d); return result; } template Digits(string s) { enum Digits = _validator!Digit(s); } void main() { import std.string: countchars; immutable d1 = "12341234"; immutable n1 = countchars(d1, "23"); assert(n1 == 4); // No array contravariance (through the Digit pre-condition): Digit[] d2 = d1; // error. Digit[] d3 = Digits!d1; // OK // No array covariance, countchars requires a // immutable(char)[] and refused a Digits[]: immutable n2 = countchars(d3, "23"); // error immutable n3 = countchars(d3, Digits!"23"); // error } // End program ------------------------------- The first problem is with array literals (here the array literals are strings, but a normal dynamic array of chars is a similar use case). If I define a subtype, like Digits, then I'd like a nice ways to write them in an array/associative array literal. Such literals should be compact, readable and yet they should be safe, this means if in a string meant to become a Digits[] I put a "x", the compiler should give me a compile-time error instead of a run-time error. To solve that contravariance+validation problem here I've used a template and a compile-time function helper. It's not a too much bad solution, but maybe there are ways to improve the situation. The other problem is that a Digit[] despite being meant as a subtype of char[], doesn't have covariance, so std.string.countchars() doesn't accept a Digit[]. This makes such subtyping much less useful. A built-in annotation like this doesn't solve the problem: subtype alias d this; Maybe a built-in annotation this this is enough, I don't know: subtype(char) struct Digit { ... } Bye, bearophile
Dec 17 2012