What D or C++26 can do, is a subset of Eiffel capabilities, or more modern approaches like theorem proving in tools like Ada/SPARK, Dafny, FStar,...
Anyway, I used the DM C++ compiler originally because it was the only one I could download to the high school computers without filling out a form, and pimply-face youth me saw "DESIGN BY CONTRACT" at the top of the website and got kinda excited thinking it was a way to make some easy money coding online.
Imagine my disappointment when I saw it was just in/out/invariant/assert features. (I'm pretty sure D had just come out when I saw that, but I saw `import` instead of `#include` and dismissed it as a weenie language. Came back a couple years later and cursed my younger self for being a fool! lol)
`import` is so cool we extended it to be able to import .c files! The D compiler internally translates them to D so they can be used. When this was initially proposed, the reaction was "what's that good for?" It turned out to be incredibly useful and a huge time saver.
The concept is sort of like C++ being a superset of C and so being able to incorporate C code, except unlike C++, the C syntax can be left behind. After all, don't we get tired of:
struct Tag { ... } Tag;
?What's the thing with the syntax? If you don't intend to use the type elsewhere don't give it a tag, if you want, you have to give it a name. (Assuming you are annoyed by the duplicate Tag)
struct Tag { ... }
or: typedef struct Tag { ... } Tag;
? It's just simpler and easier to write code in D than in C/C++. For another example, in C/C++: int foo();
int bar() { return foo(); }
int foo() { return 3; }
The D equivalent: int bar() { return foo(); }
int foo() { return 3; } struct Tag { ... };
if it needs to rely on the internals, but the user shouldn't care: typedef struct { ... } Tag;
if it can be opaque (what I would default to): typedef struct {} Tag;
I also think that is a good feature to separate specification from implementation, I like being forced to declare first what I want to implement. Funnily in your special case you wouldn't need the declaration. (But of course it's a bad idea to rely on this "feature")Modern C++ is slowly adopting D features, many of which came from extensions I added to my C++ compiler.
Checking input parameters is easy, just write asserts at the start of the function.
Checking result requires "destructor" block and some kind of accessible result variable, so you can write asserts in this destructor block which you can place at the start of the function, as well.
Checking class invariants requires a way to specify that some function should be called at the end of every public function. I think, it's called aspect-oriented programming in Java and it's actually useful for more things, than just invariant checking. Declarative transaction management, logging.
There are probably two schools of programming language designs. Some put a lot of features into language and other trying to put a minimal number of features into language which are enough to express other features.
Same reason function calls are better than arbitrary jumps.
But what I love the most is: https://news.ycombinator.com/item?id=43936007
Instead of:
const MIN_U32 = 0;
const MAX_U32 = 2 ** 32 - 1;
function u32(v) {
if (v < MIN_U32 || v > MAX_U32) {
throw Error(`Value out of range for u32: ${v}`);
}
return leb128(v);
}
You can do this, in Ada: subtype U32 is Interfaces.Unsigned_64 range 0 .. 2 ** 32 - 1;
or alternatively: type U32 is mod 2 ** 32;
and then you can use attributes such as: First : constant U32 := U32'First; -- = 0
Last : constant U32 := U32'Last; -- = 2 ** 32 - 1
Range_ : constant U32 := U32'Range; -- Range 0 .. 2**32 - 1
Does D have anything like this? Or do any other languages?is it not the same as the one in Eiffel?
these are just runtime assertions
EDIT: how am i getting downvoted for copy-pasting literally what the article verifies?
int foo(int a) {
assert(a > 5);
int b = a * 10;
assert(b > 50);
return b;
}
do you think those asserts don't "run automatically"?Like: software programs can't be that difficult to create properly because they are just 1s and 0s.
See also the scope(exit) feature.
https://en.cppreference.com/w/cpp/experimental/scope_exit.ht...
He demonstrated it with C++ templates, but the D one is far more straightforward.