Hacker News new | ask | show | jobs
by Flankk 1545 days ago
> Real Hackers have also known, for a while, that C and C++ are not appropriate for most programs that don't need to do arbitrary bit-fiddling.

Strongly disagree with this statement. I've read it so many places now that it has to be a meme. I actually wish I could use C++ on the web instead of this JS nightmare ecosystem. I don't understand where the idea comes from. I'm never "bit-fiddling" in C++ and almost never need to use pointers.

6 comments

In my experience the best for "bit-fiddling" is Erlang (and, by extension, Elixir) which offers bit-string literals[1], along with pattern matching on them. It's trivial to implement any binary protocol or parse any binary file format with these. It makes bit-fiddling pleasant and fun, but nobody ever mentions Erlang in these discussions.

That's because most programmers are incapable of making any informed decision about the language they use (and, even more so, about languages they don't use). There's a strong tribal mentality, a lot of cargo-cults, and the very narrow perspective on what's possible and (more importantly) what's desirable is prevalent.

[1] https://www.erlang.org/doc/programming_examples/bit_syntax.h...

Common Lisp has bit string literals:

    Welcome to Clozure Common Lisp Version 1.11-r16812M  (DarwinX8664)!
    
    ? #*010010010101001
    #*010010010101001
    ? (type-of *)
    (SIMPLE-BIT-VECTOR 15)
I think it's not unusual to have base-x number literals (even Python got `0b01101` literals at some point), but not many languages support pattern matching on bitstrings. In Erlang, it looks like this:

    1> A = 2#0010010010101001.
    9385
    2> << _:2, B:4, _/bitstring >> = << A:16 >>, B.
    9
    3> io:format("~.2B~n", [B]).
    1001
I put your number into 16-bit bitstring[1], then ignored first 2 bits, extracted the next 4 bits, and ignored the rest.

CL doesn't have pattern matching in the standard, IIRC, but there are libraries implementing it, so I wouldn't be surprised if one of them also offered bitstring matching, but that's beside the point: I'm comparing Erlang and C++ here, not Erlang and CL.

[1] It could be 14 or 15 bits, but I wanted to have a bit of a leading padding to ignore in the pattern.

EDIT: I missed the fact that the #*01... literal in CL is not a number, my bad. The equivalent literal would be << 2#01...:N >> in Erlang, but you need to give the N (number of bits) yourself, so it's a bit less convenient.

Whoever says things like that probably means "appropriate" in the sense that you can get your stuff done with another language using a fraction of the implementation time.

And whoever wishes to use C++ on websites... who is stopping you since Webassembly? Speaking about ecosystems... I also don't think the package management ecosystem in C++ is that much better, right? And there are enough horror stories about illegibility and foot-guns even in modern C++ code, rivaling the worst YOLO frontend style...

C++ requires you to be a lot more verbose and precise for almost everything. That translates to more work, and the benefit isn't automatically worth anything.

Wasm is bleeding edge. AFAIK the only compatible UI library is Qt and support is not production ready. I have never needed package management in C++. There are gotchas with all languages, Lisp is not a panacea. Language verbosity is not bad it's a tradeoff, functional languages are usually hard to read. The language requiring you to be precise is a good thing. There's a reason the web industry has moved to TypeScript.
Wasm is not just bleeding edge, it is supported by all major browsers and being used in all sorts of real-world websites. No, "Qt" is not the only way to do UI in C++/wasm. This is a basic misunderstanding of the technology. Wasm lives inside the Javascript vm and can manipulate DOM objects all day long. It's just not very practical to do so. There are plenty of Rust projects going in that direction, though...

C++ doesn't only require you to be precise, it requires you to be verbose. JS is quite precise, and a lot more expressive because of the runtime. TypeScript is all of this and also allows you to be more explicit in order for the compiler to check your work, much like a proof checker.

The C++ type system is relatively stupid compared to that of TypeScript and F#, for example. In TS and F#, you can use types to help you, in C++ you already need the types because otherwise the compiler doesn't have a clue what to do.

On the opposite end, Common Lisp is actually pretty decent for bit twiddling. It has the operators from the PDP instruction set, LDB and DPB, which load and deposit bytes of varying length from and into other numbers.
Webassembly might be the solution to your problem
On the frontend. In a number of years. It's in its infancy. Instead of hacking a webpage to behave like software it actually will be software. So I'm pretty excited about the idea.
I like working in C++, after a decade of working in Java, Python, Javascript and Clojure, I find working in C++ (which I learned before these other languages) to be quite fun and pleasant, at least with relatively modern C++.

I've been, on and off, working on a little toy game engine, for a few years. Its a mix of keeping up with C++ advancements, learning various concepts like physically based rendering, and just the fun of crafting a big project, with no constraints other than my time and ability, no deadlines, no expectation of releasing anything. Its cathartic and enjoyable. I really do enjoy it.

Last September, I got frustrated with something I was working on in a more serious capacity. It was some server software, it responded to HTTP requests, it accessed third party services over HTTP and Websockets, it talked to a Postgres database. Overall it was an event driven system that transformed data and generated actions that would be applied by talking to third party services. The "real" version was written in Clojure and it worked pretty well. I really like Clojure, so all good.

But because I was frustrated with some things about how it ran and the resources it took up, I wondered what it would be like if I developed a little lean-and-mean version in C++. So I gave it a try as a side project for a few weeks. I used doctest[1] for testing, immer[2] for Clojure-like immutable data structures, [3] lager for Elm-like application state and logic management, Crow[4] for my HTTP server, ASIO[5] and websocketpp[6] for Websockets, cpp-httplib[7] as a HTTP client and PGFE[8] for Postgres, amongst some other little utility libraries. I also wrote it in a Literate Programming style using Entangled[9], which helped me keep everything well documented and explained.

For the most part, it worked pretty well. Using immer and lager helped keep the logic safe and to the point. The application started and ran very quickly and used very little cpu or memory. However, as the complexity grew, especially when using template heavy libraries like lager, or dealing with complex things like ASIO, it became very frustrating to deal with errors. Template errors even on clang became incomprehensible and segmentation faults when something wasn't quite right became pretty hard to diagnose. I had neither of these problems working on my game engine, but both became issues on this experiment. After a few weeks, I gave up on it. I do think I could have made it work and definitely could go back and simplify some of the decisions I made to make it more manageable, but ultimately, it was more work than I had free time to dedicate to it.

So my experience was that, yes, you can write high level application logic for HTTP web backends in C++. You can even use tools like immer or lager to make it feel very functional-programming in style and make the application logic really clean. Its not hard to make it run efficiently both in terms of running time and memory usage, certainly when comparing to Clojure or Python. However, I found that over all, it just wasn't as easy or productive as either of those languages and I spent more time fighting the language deficiencies, even with modern C++, than I do when using Clojure or Python.

I think I would think very long and hard before seriously considering writing a web backend in C++. If I had the time, I'd love to retry the experiment but using Rust, to see how it compares.

[1] https://github.com/doctest/doctest

[2] https://github.com/arximboldi/immer

[3] https://github.com/arximboldi/lager

[4] https://github.com/CrowCpp/crow

[5] https://think-async.com/Asio/

[6] https://www.zaphoyd.com/projects/websocketpp/

[7] https://github.com/yhirose/cpp-httplib

[8] https://github.com/dmitigr/pgfe

[9] https://entangled.github.io/