They have a really interesting blog overall.
3,780 karma · joined February 17, 2013
They have a really interesting blog overall.
cxx also can only handle a subset of the interfaces expressive in C++. If you haven’t written the interface with the specific goal of making it usable via cxx, it’s pretty likely you’ll have issues wrapping it with cxx.
It's much worse in one way: Interoperation with existing C++ code. Sure, that's not a fair criteria - C++ is designed in a way that makes it almost impossible for other languages to use C++ libraries without a heavyweight wrapper like SWIG. However, even though it's not fair, it's still really important. If you have a project like LLVM with millions of lines of existing C++ code, adding expensive or complicated interop boundaries between different components within your system is not an acceptable price to pay.
You probably already know this, but if you're willing to take a dependency on Boost.Iterator, then boost::iterator_facade[1] makes it much easier and less error-prone to implement a standards-conforming iterator, and the pre-built iterator adapters[2] cover lots of common cases, so you don't need to directly implement an iterator at all.
Not arguing the relative merits of C++ vs. Rust, just leaving a pointer here for anyone who didn't know about it.
[1] https://www.boost.org/doc/libs/1_66_0/libs/iterator/doc/iter...
[2] https://www.boost.org/doc/libs/1_66_0/libs/iterator/doc/inde...
If you’re changing the interface of an RPC service, then you can’t do that in a single commit, and need to fall back to something like the second approach, but with even more caution to make sure you properly account for releases and the possibility of rollbacks.
2. You create a PR that fixes the code and the problematic call sites in a single commit. It gets merged and you’re done.
In the multi-repo world, you need to instead:
1. Add conditional branching in your library so that it supports both the old behavior and new behavior. This could be an experiment flag, a new method DoSomethingV2, a new constructor arg, etc. Depending on how you do this, you might dramatically increase the number of call sites that need to be modified.
2. Either wait for all the problematic clients to update to the new version of your library, or create PRs to manually bump their version. Whoops - turns out a couple of them were on a very old version, and the upgrade is non-trivial. Now that’s your problem to resolve before you proceed.
3. Create PRs to modify the calling code in every repo that includes problematic calls, and follow up with 10 different reviewers to get them merged.
4. If you still have the stamina, go through steps 1-3 again to clean up the conditional logic you added to your library in step 1.
Basically, if code calls libraries that exist in different repos, then making backwards-incompatible changes to those libraries becomes extremely expensive. This is bad, because sometimes backwards-incompatible changes would have very high value.
If the numbers from my example were higher (e.g. 1000 call sites across 100 teams), then the library maintainer in a monorepo would probably still want to use a feature flag or similar to avoid trying to merge a commit that affects 1000 files in one go. However, the library maintainer’s job is still dramatically easier, because they don’t have to deal with 100 individual repos, and they don’t need to do anything to ensure that everyone is using the latest version of their library.
For mutable objects, the notion of equality is hairy in general, because what you want often depends on why you'd be comparing the two objects. You might have two mutable objects that can be meaningfully compared in your business logic, but absolutely should not be used as keys in a map. Often you can satisfy your goals by implementing a separate method that does not attempt to conform to the 'equals' contract, which ensures it will not unintentionally be used for e.g. data structure ordering.
[1] https://github.com/google/auto/blob/master/value/userguide/i...
[2] https://projectlombok.org/features/EqualsAndHashCode
[3] https://blogs.oracle.com/javamagazine/records-come-to-java
IIRC clang implements it as well, but I wasn’t able to find a reference to it in their docs.
"You can't make rent"/"You can't buy a house with a reasonable commute" an a software dev salary is almost entirely a California and NYC-area phenomenon.
A "typical" software developer (even a junior) could afford a decent house within a reasonable commute in ~7 of the top 10 metro areas in the US (Chicago, Dallas, Houston, Miami, Philadelphia, Atlanta). In the remaining 3 (NYC, LA, DC), you'd probably end up with an unpleasantly long commute, although plenty of people make that choice. If you go further down the list of metros, the ratio is similar.
> How long does it take to buy a house/apartment?
In any of the metro areas mentioned above, you should be able to buy a house on a software dev salary as soon as you've save a 5-10% down payment (so $25-50k for a $500k house, more if you want something bigger/in a nicer area). The difference in salaries vs. Europe would typically allow you to save that within a couple years.
> Can you afford to travel on vacation?
Unambiguous yes - you can afford the monetary cost of a vacation on a software dev salary. Families in much less lucrative fields than software still take vacations.
Paid time off is trickier - European norms are for employers to provide much higher amounts of PTO for all employees, while most American firms are much stingier with it. This is something to explicitly shop around for and use as a decision criteria in a job hunt. There are definitely large American firms that provide 20-25 PTO days standard for new employees.
> Can you save money for your kids' college (or do you even need to do that)?
Annual tuition & mandatory fees at the flagship state university in the median state is ~$12k, so ~$48k for a 4-year degree. This excludes living costs, but you have to pay living costs at European universities as well. If returns on your college investments keep pace with tuition increases (many states have programs that can explicitly guarantee this), then you can pay tuition after 18 years by saving $2700/year per child.
You didn't mention healthcare, which often comes up, but software devs working as full-time employees will typically have good health insurance available through work, so that's not a problem in practice either.
There are tons of reasons to prefer Europe vs. the US (culture, a preference for dense living, lower-pressure work environments, more paid time off, etc.) but overall buying power isn't really one of them. Your salary will buy you more "stuff" (housing, cars, vacations, savings, etc.) in the US, unless you choose to live in one of the highest-cost regions of the country without a correspondingly high salary.
If this was a sale to a PE firm I think your predictions would be more likely, but Nvidia seems really unlikely to be a “slash costs and sell it for parts” type of buyer.
Naval flags would be higher bandwidth if you could pre-arrange a modest-sized dictionary of the words and phrases you’d need.
https://www.navalgazing.net/Signalling-Part-1 is a good read.
Disabling exceptions isn’t “fighting against how everyone else writes the language” - it’s pretty common and well-supported.
Obviously there is still significantly more diversity at the low end of the embedded world, but you wouldn’t run Linux on e.g. an MSP430, even if you somehow had a compiler that would support that.
#2 is still currently tricky, but Rob Landley (former Busybox maintainer) is working on a full bug-for-bug compatible Bash clone called toysh which will be included in an upcoming release of Toybox[1]. Once that’s released, I’m looking forward to (hopefully) never writing a script for BusyBox ash again.
I believe this leaves Apple, ARM, Fujitsu, and Marvell as the only companies currently designing and selling cores that implement the ARM instruction set. That may drop to 3 in the next generation, since it’s not obvious that Marvell’s ThunderX3 cores are really seeing enough traction to be be worth the non-recurring engineering costs of a custom core. Are there any others?
That being said, you may not need it, because Postgres/PostGIS can scale vertically to handle larger datasets than most people realize. I recommend loading your intended data (or your best simulation of it) into a Postgres instance running on one of the extremely large VMs available on your cloud provider, and running a load test with a distribution of the queries you'd expect. Assuming the deliberately over-provisioned instance is able to handle the queries, you can then run some experiments to "right-size" the instance to find the right balance of compute, memory, SSD, etc. If it can handle the queries but not at the QPS you need, then read replicas may also be a good solution.
Catalyst was released in 2005 (so still after Rails), and definitely didn’t provide Rails-like productivity.
If Mojolicious had been available in ~2003 or earlier, it’s entirely possible Ruby never takes off, because developers could get similar productivity in a more “known”/“mainstream” language.
Catalyst (released 2005), Mojolicious (2008), and Dancer (2009) were all released too late to matter.
The most interesting counterfactual is “What if someone had written something like Rails for Perl before 2005?” It was definitely technically possible, and it might have made Perl take back off (Ruby usage grew from basically nothing due to Rails), but the community’s focus on Perl 6 at the time made it much less likely.