Hacker News new | ask | show | jobs
by jbandela1 3804 days ago
Wow, this is the first post I have ever read that even kind of implied that Andrei Alexandrescu was a Blub programmer.

Part of being a Blub programmer is that you don't even think about the issues. In regards to the weird features brought up, the underlying issues behind these features have been in the C++ consciousness for some time. Below are some talks and resources covering at least some of these issues.

Sean Parent - Inheritance is the Base Class of Evil - https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&c...

Herb Sutter - You don't know const and mutable - http://herbsutter.com/2013/01/01/video-you-dont-know-const-a...

Andrei Alexandrescu - Systematic error handling in C++ - https://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012...

Herb Sutter - Writing Good C++ by Default - https://www.youtube.com/watch?v=hEx5DNLWGgA

Andrew Sutton - Generic Programming with Concepts Lite - https://www.youtube.com/watch?v=qwXq5MqY2ZA

One of the things that helps with avoiding "Blubness" in C++ is the significant interest in languages such as Haskel (which is not considered a Blub language by anyone except Agda programmers) and in applying the techniques and insights where possible to C++ whether through writing new libraries (see for example Fit by Paul Fultz II -https://github.com/pfultz2/Fit) or through new language features (see this post by David Sankel - http://davidsankel.com/uncategorized/c-language-support-for-...)

Finally, is also interesting that Paul Graham's blub paradox is being brought up in regards to Rust, C++, and D. The Paul Graham article is in large part talking about the power of meta-programming. In this regard, D and C++ are significantly more powerful in that regard. Features like higher kinded types (template templates), variadics, and non-type template parameters help in this matter. When you can write a function that can generically work with a tuple with any number and type of parameters, you can do some pretty neat stuff. For some examples take a look at Boost.Hana by Louis Dionne (http://boostorg.github.io/hana/). In this regards, Rust is actually the Blub compared to D and C++.

4 comments

C++'s templates are untyped. Rust's templates are typed. Most people aren't aware of the difference, and they naturally think that templates "have to work" like the ones in their favorite language (dynamically typed if coming from C++ and D, and statically typed if coming from Java, C#, or most other languages). But the fact that Rust and C++/D picked different sides of the tradeoff is the key source of the differences between them.

C++ and D programmers, like you (and Andrei), look down on Rust generics and give examples of all the things that you can't do with Rust generics that are easy to do with C++ templates. But there's an equally strong counterargument, in that Rust generics never give errors at template expansion time and are guaranteed to expand to valid code. This makes code easier to understand, improves the experience for users of your generics, and also simplifies the implementation, leading to potentially better compile times (since you typecheck once instead of after every template expansion). Of course, this is a tradeoff: it's more work for us to implement the features necessary to do the kinds of sophisticated metaprogramming you see in C++ and D, and there will always be some things you can't do in Rust that are easy in C++ and D. But that isn't a slam-dunk argument for untyped templates vs. typed generics any more than easy reflection is a slam-dunk argument for dynamic typing like Python vs. static typing like Java.

> In this regards, Rust is actually the Blub compared to D and C++.

I think this demonstrates a significant weakness in Blub as a concept: there is not even a partial ordering of languages by power. The essay only works because Graham picks the two sides of the debate: Lisp, which Graham believes to be the most powerful of languages, and Blub, a theoretical language that can be stipulated to be less powerful than Lisp in all ways.

Outside the essay, "blub" only exists as a slur for a despised language or an insult for another programmer, and it's only useful as a way to start arguments.

  > In this regards, Rust is actually the Blub 
I'm not so sure. We are aware of the features that they have; we just prefer the strongly-typed versions to the stringly-typed[1] versions.

We do desire more meta-programming features, and they will happen. Like all decisions, we don't want to rush into them.

1: This is not _entirely_ accurate, but I'm slightly at a loss for how to exactly characterize this at this particular moment. Rust's metaprogramming guarantees that you always generate valid Rust code, D's does not.

The last statement was more in regards to the Blub definition implied by the article. Of course, people who are immersed in programming language theory are not Blub programmers - they are aware of what is possible, but are also aware of the inherent tradeoffs.

With regards to Rust, do you have any idea when more meta-programming features like variadics and non-type template parameters might be available in the language (are we looking at months, years, or decades)? Rust, has a lot of features that really interest me, but seeing the tuple serialization code brought back bad nightmares of simulating variadic templates using macros in C++ before I had a compiler that supported C++11 variadics. To me, at least personally, it felt like a step backward from C++14, and kind of curtailed my enthusiasm for doing a deep dive into the language. My test for the power of a language's type manipulation is how easy is it to write an implementation of apply(Function f, Tuple t) which will call f with the values of t. I would be most interested to see how Rust will implement this kind of metaprogramming.

Yeah, I agree with my sibling comment above that Blub is kind of a weak concept for this reason.

It's hard to say because the work for those features hasn't even been started; the MIR refactoring is still underway. Once that's done, RFCs for this stuff will start to appear, and we'll have a better idea of overall schedule. I would say that the current schedule is "longer than months, shorter than a few years".

I myself _really_ want higher kinded types, but at the same time, I would rather wait and do it right than rush and regret thing slater. We have a solid language as it is; the need to get these more advanced features is not particularly urgent, in my opinion. I like to think on the long scale when it comes to the language: if it's going to be around 40 or 50 years, we're in year one. There's plenty of time.

> My test for the power of a language's type manipulation is how easy is it to write an implementation of apply(Function f, Tuple t) which will call f with the values of t. I would be most interested to see how Rust will implement this kind of metaprogramming.

That's kind of a weird litmus test of the power of the language's type manipulation: it only applies to languages where functions take multiple arguments, it's a pretty niche use case (since the workaround in Rust is straightforward), and there's nothing particularly sophisticated about variadic generics (what you need to solve the problem). I could equally say that my litmus test of a language's generics system is whether the compiler prevents errors during template expansion.

Anyway, to answer your question: that's really easy in Rust, as long as you're on nightly. The FnMut trait (and friends) allow you to call functions with tuples as arguments. https://doc.rust-lang.org/std/ops/trait.FnMut.html

Is that mostly a faster feedback loop and better errors thing? It seems like so long as the generated code doesn't get as far as compiling, it doesn't make that much of a difference?

(this could easily be a stupid question; I know I've come across as condescending to you before by mistake and if I've somehow done it again please believe that I meant to come across as genuinely curious :)

There are a number of benefits to concepts:

- They make namespacing of functions easier, eliminating the need for C++'s "argument-dependent lookup". The issues here are somewhat subtle and would take a lot of space to explain. But the end result is that we can remove a massive amount of confusion by getting rid of ADL.

- Error messages are much better, because the insides of templates never leak to users of the template.

- Typechecking is simplified, because we only have to typecheck each template once, at the time of definition, as opposed to repeatedly typechecking it from scratch every time it's instantiated. This, in theory, allows compilation to be faster.

> Error messages are much better, because the insides of templates never leak to users of the template

This is unequivocally a good thing - I think maybe my disconnect here in how excited I am compared to others is that I'm comparing it to the experience of debugging lisp macros and everybody else is comparing it to the bottomless pit of despair that is C++ template errors ;)

Not at all!

Yes, to me, it's largely about better errors and such. If th generated code is wrong, it won't compile, so it's not _that_ level of bad. But this can't happen in Rust: http://tgceec.tumblr.com/

Now I want to see an article that compares the error messages from rust and D metaprogramming ... though admittedly, at least half of this is because you could call said article "D missed nosejob day".
Note that with bounded polymorphism you get clear API boundaries too. With templates you may have to clearly document what kind of type is allowed in.

There's also the danger of something compiling where it shouldn't.

I would go one step further and say that those features in Rust (and ML, Haskell etc) aren't even metaprogramming. So D uses metaprogramming to make up for a weaker type system.
I like to call C++ templates "structurally typed", since you can get some degree of that from SFINAE and composing templates together. They're more pattern-matching based than type-based. This is reminiscent of how Go auto-impls interfaces, really.
It's always easier to see the blub in someone else's language and not in our own.