My understanding is that RC is relatively expensive in time (especially for atomic RC) but uses a lot less memory than state of the art fast GC. And RC doesn't handle cycles.
HN user
ntrel
D doesn't store capacity in each slice. This allows a slice to fit in registers more often. Instead for GC allocated slices, the GC will store metadata before the first element of the allocation. That does make it slower to access, particularly when the slice points past the first element, but it is cached to speed up repeated accesses to the same allocation. Repeated appending can be further speeded up by using a dedicated Appender type.
Because Go designers don't like OOP and didn't want low-level system programming as core features. They also were not keen on generic programming. Basically they wanted a simpler language. (Then they realized generics are useful, ironically their constraints add complexity). Also they wanted a segmented stack and coroutines + channels as language features.
This compiles:
ref ubyte[n*2] requires_ptr_twice_as_large_as_input(uint n)
(
const ref ubyte[n] input,
ref ubyte[n*2] output,
) {
output[0..n] = input[0..n];
output[n..2*n] = input[0..n];
return output;
}
void main()
{
ubyte[10] input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
ubyte[20] output;
requires_ptr_twice_as_large_as_input!(10)(input, output);
import std.stdio;
writeln(output);
assert(output == input ~ input);
}Why is your proposal better than this:
import std.sumtype;
void main(){
struct A { int a; }
struct B { string b; }
struct C { bool c; }
alias TaggedUnion = SumType!(A, B, C);
auto tgu = TaggedUnion(B("hi"));
int i = tgu.match!(
(A a) => a.a,
(B b) => b.b.length,
(C c) => c.c * 5
);
assert(i == 2);
}
If you miss out a `match` handler for any of A, B, C you get a compile-time error. Or you can use a generic handler which will be instantiated for any type not explicitly handled.
https://dlang.org/phobos/std_sumtype.htmlClass instances can go on the stack too using `scope`:
scope obj = new Object;
...
// destroyed at end of scopeArrays and slices really have nothing to do with generic programming. Java has poor generic support (type erasure) and C++ has poor syntax and a bad design for iterators. Languages with decent generics support have none of these problems.
If this is 'armchair criticism' why do Go's designers say they are considering adding generics support?
Lack of generics does not ease development speed. Generic programming is about safe reusability. (Development speed includes the test, debug, fix cycle).
No generics actually harms code clarity and destroys type safety.
C's preprocessor means C code can often do interesting tricks, such as the X macro: http://www.drdobbs.com/the-new-c-x-macros/184401387
There are tons of other interesting uses for macros. Obviously I'd rather a language had safer equivalents to a C preprocessor.
None of those things cause as much greenhouse gas emissions as a high meat diet.
The level of meat consumption in rich countries is unjustifiable.
> C++ has the best (imperative) language support for templates
D's template support is far superior: static if, constraints, compile-time function execution, string mixins, opDispatch. These features make templates much more practical and more powerful.
Actually it is simple: eat less meat. Meat production is vastly more wasteful than vegetable production calorie-for-calorie.
The problem is it's no better than C - the correct way is to return sum types, either values or errors. A good language would statically check that any returned values are only used when there are no errors, preventing invalid values being accessed.
This requires some flow analysis, but brings real benefit and safety.
> D's garbage collection is global, and either off or on
That makes it sound like you can't use GC and manual memory management together; you can - std.container uses manual memory management internally for max efficiency.
> things that were mutable are still mutable
`string` is immutable. You can use immutable everywhere if you like. C++ doesn't even have transitive const.
> templates are still templates
With constraints, unlike C++.
> hard-to-solve threading problems are just as hard to solve
Have you looked at D 2.0? Globals are thread-local by default, unlike C++. Implicit sharing is disallowed, unless immutable.
> region pointers
It's early days (perhaps I don't fully get region/borrowed pointers yet) but D's `scope` parameter keyword seems very similar. It prevents an argument escaping the function call.
> lack of nulls
This is the big one. Unfortunately D doesn't seem to have an answer on this. I understand Rust uses option/sum types for this, which seems like a great idea.