HN user

schveiguy

143 karma
Posts0
Comments33
View on HN
No posts found.

To be fair, the release cadence has been in a bit of a mess lately. But I expect that to be fixed soon. We don't want 6 months between releases.

gdc is 100% Iain Buclaw. But he and Walter collaborate on needs for gcc compatibility, as long as Iain is around, gdc will be around.

It is true we have a small team. But we are a dedicated team.

No, templates are only needed to introduce new symbols. And D templates are vastly superior to C++. D's superpowers are CTFE, static if, and static foreach.

auto is used as a return type because it's easy, and in some cases because the type is defined internally in the function and can't be named.

You would not like the code that uses auto everywhere if you had to type everything out, think range wrappers that are 5 levels deep.

ooooold drama. Like 2008.

FOSS: DMD was always open source, but the backend license was not compatible with FOSS until about 2017. D is now officially part of GCC (as of v6 I think?), and even the frontend for D in gcc is written in D (and actively maintained).

D1 vs. D2: D2 introduced immutability and vastly superior metaprogramming system. But had incompatibilities with D1. Companies like sociomantic that standardized on D1 were left with a hard problem to solve.

Tango vs phobos: This was a case of an alternative standard library with an alternative runtime. Programs that wanted to use tango and phobos-based libraries could not. This is what prompted druntime, which is tango's runtime split out and made compatible, adopted by D2. Unforutuntately, tango took a long time to port to D2 and the maintainers went elsewhere.

gc vs. nogc: The language sometimes adds calls to the gc without obvious invokations of it (e.g. allocating a closure or setting the length of an array). You can write code with @nogc as a function attribute, and it will ban all uses of the gc, even compiler-generated ones. This severely limits the runtime features you can use, so it makes the language a lot more difficult to work with. But some people insist on it because it helps avoid any GC pauses when you can't take it. There are those who think the whole std lib should be nogc, to maximize utility, but we are not going in that direction.

Thank you for this post. I can tell you that we do appreciate comments like this, and the deficiencies you cite are many of the reasons we are rewriting phobos and druntime.

The time module "lied" seems like a straight up bug. Can you give any more details on it?

Why "a"

`a` is a parameter in the lambda function `a => a.idup`.

Why "map!"

This is definitely something that can trip up new users or casual users. D does not use <> for template/generic instantiation, we use !. So `map!(a => a.idup)` means, instantiate the map template with this lambda.

What map is doing is transforming each element of a range into something else using a transformation function (this should be familiar I think?)

FWIW, I've been using D for nearly 20 years, and the template instantiation syntax is one of those things that is so much better, but you have to experience it to understand.

"idup" seems arbitrary

Yes, but a lot of things are arbitrary in any language.

This name is a product of legacy. The original D incarnation (called D1) did not have immutable data as a language feature. To duplicate an array, you used the property `dup`, which I think is pretty well understood.

So when D2 came along, and you might want to duplicate an array into an immutable array, we got `idup`.

Yes, you have to read some documentation, not everything can be immediately obvious. There are a lot of obvious parts of D, and I think the learning curve is low.

import C is not perfect. There are pieces of C that don't map directly to D. Such as #define constants and macros.

That being said, it will make writing bindings a LOT easier, even though D already has direct binding to C functions.

The rationale is that in a correctly written program, an Error should never be thrown. It's similar to UB in C. The compiler can assume Errors are never thrown, and so it can not worry about cleanup in nothrow functions.

But the nice thing is, it reuses the same handling mechanisms as exceptions. You don't have to create something different for handling Errors. In fact, the code that prints error stack traces and exits is the same code that handles exceptions.

Consequently, this is why you shouldn't catch them, or at least not catch them and continue. The exceptions are unittests and contract asserts, where the compiler does guarantee proper stack unwinding.

Why I Like D 5 years ago

The only way you can be saying this is if you haven't experienced metaprogramming in D. C++ does not compare at all. Generics do not compare at all.

You can take D metaprogramming from my cold dead hands.

Why I Like D 5 years ago

You can use arrays as if they were individual operands, and it will expand out the loop and apply the expression to all the values (and can use optimization/vector tricks if posssible).

e.g.:

arr1[] += arr2[] / 10.0 + 5;

TBH, I don't use this feature much, because I work with ranges more than arrays, which do not have this ability. This feature predates ranges (and the std.algorithm.map function, which can do what you say as well).

Why I Like D 5 years ago

the "Split stdlib" thing is about 15 years out of date (and only applied to D1, whose final release was in 2012).

I wish that criticism would go away.

Why I Like D 5 years ago

What language are you used to that doesn't do this? I think I would go nuts if I had to always use the fully qualified name for all symbols.

Driving with D 5 years ago

There are "bad" uses of UFCS, and good ones (sometimes depending on preference). For example, I hate code like `1.writeln`.

The major feature that it provides is pipelining (as shown in the article)

Yes, it supports interfaces and unions. One thing not being stated enough in this thread also is that the docs are not just a regurgitated version of the prototypes -- there's actual hand-written text that tells you what the things return.

What am I looking at there? Are those all traits on Vec that I then have to parse mentally so I can understand what I can do with it? Are all those pages basically to say "Vec works like an array of T"?

I've dealt with generics in other languages such as Swift and C#, and they were substandard to D's templates IMO. I remember in C#, I could not get a simple generic function that accepted both a string and Int to work, so I just gave up and wrote multiple functions without generics.

I'm sure some people find this documentation helpful, but it doesn't look as useful to me as map's simple one-liner.

Yes, this is the problem for returns, but it's going to be difficult for the compiler to put something useful. The best it can do is point you at the code that returns, and let you figure it out.

I still think the best option is let the author describe it in ddoc, as the semantic meaning can be much easier to convey that way.

This wouldn't work for D. D doesn't constrain return types to something less than what they are. A Range is not just an Iterator, it has optional pieces that depend completely on the given type.

For example, the return of map could provide indexing, or it could provide forward and backward iteration, or it might have methods that are completely unrelated to the type.

There is no good reasonable and non-confusing way to describe all the things map could return depending on the input. It's much better to just describe it conceptually in the human-readable docs, and let the person understand the result.

I'll note that just above the function map in D's source is the documentation. You just need a little more context, and it will describe what map returns in a much more (IMO) useful fashion than a return type that might be several lines long and consist of various static conditionals:

"The call map!(fun)(range) returns a range of which elements are obtained by applying fun(a) left to right for all elements a in range."

This is the difference between duck typing and generics.

You'll never learn it from reading the documentation.

Did you not see the Returns section from that link?

"Returns: A std.typecons.Tuple of the three resulting ranges. These ranges are slices of the original range."

Further note: If you just saw `std.typecons.Tuple!(typeof(Range.init[0 .. $]), typeof(Range.init[0 .. $]), typeof(Range.init[0 .. $]))` which is what would have to be written there instead of auto, would that make you feel better? Do you not have to read the documentation to figure out what the function does or what actually goes into those tuples?

Sometimes I feel like auto is definitely overused. In a recent fix, I changed something that returned a boolean (no templates involved) from returning auto to returning bool.

But sometimes auto is the best tool for the job, especially when writing wrapping types. In that case, yes, you have to read the documentation (and I mean what is written in the ddoc comments). But in many cases, you don't have to, because you recognize the pattern, or it's simply a wrap of the underlying type's function.

Mea Culpa. I installed 2016 to try and find the issue with my system, I haven't searched around the UI for bug reporting tools, didn't even know Microsoft had added them. Just found it now, indeed it looks quite useful.

I'm going to update my post with more information because actually, there's a lot of great tips from these comments!

Thanks for the information. I indeed was, after 80 minutes of phone call, not quite in a "listening" mood. I actually kind of felt bad yelling at the last person after hanging up -- it wasn't her fault I was chucked around for over an hour. I think definitely I will be more apt to try other avenues if I find another bug in the future.