HNHacker News
TopNewBestAskShowJobs

millstone

6,895 karma · joined November 23, 2012

submissionscomments
millstone··on How Tail Call Optimization Works
There's a funny interaction between TCO and memory management. If you have scoped destructors (C++, Rust) then you might accidentally defeat TCO by simply declaring a variable. GCs solve this problem by deferring collection to allocation points, but now TCO requires GC.

What's the modern view here? I think it's bimodal: either TCO is a defining feature of the language, or a best-effort optimization that nobody should rely on.

millstone··on Ask HN: What does mastery look like in software engineering?
Functional programming is taught in schools, so engineers straight out of college know it. I was one of them!
millstone··on Rust is now overall faster than C in benchmarks
A programming language idiom is a pattern or technique that you expect your readers to know, even if it isn't obvious when encountered for the first time. Here's an idiom:

    for (int i=0; i < 10; i++)
We all instantly know this means loop 10 times, from 0 through 9. But on first read it takes a little work to figure out what's happening.
millstone··on Rust is now overall faster than C in benchmarks
But this is the crux. What sorts of aliasing are permitted in unsafe Rust? I think we kind of don't know; that's what the "stacked borrow" effort is trying to answer.
millstone··on Rust is now overall faster than C in benchmarks
What you describe about 'const' is just about const correctness. That's important but different than aliasing.

For example consider Slice::swap [1]. This does consider the possibility that the pointers alias, and correctly, because they might point at the same object.

https://doc.rust-lang.org/src/core/slice/mod.rs.html#541-553

millstone··on Rust is now overall faster than C in benchmarks
I don't agree with the first paragraph at all. C++ templates are more powerful than Rust generics, and also easier to write, because they are not inherently type-checked. In practice templates are embraced and used extensively, not "avoided at all costs" (like C++ exceptions.)
millstone··on Rust is now overall faster than C in benchmarks
Maybe but there's reasons to doubt this. For starters, it's not obvious that Rust copies less. Sometimes you copy in Rust because it's easier than threading lifetimes throughout; sometimes you copy because you are defending against an imaginary threat (consider std::env::var or std::env::args).

One potentially important difference is integer indexes vs pointers. Compared to C, Rust uses int indexes less often within a function (iterators, not for loops) but more often between functions: in C you might store a pointer somewhere, while in Rust it's easier to store an index into a collection. But a ton of work has been poured into LLVM's induction variable analysis so this is swimming upstream.

The aliasing could be really important; there's a ton of pessimizations for e.g. uint8 pointers. Part of the maturing is fully specifying Rust's UB and aliasing model.

millstone··on A half-hour to learn Rust
The operator overloading is nice but you still get smacked in the face right away by the borrow checker. Simple stuff like this won't compile ("use of moved value"):

    let a = Integer::from(10);
    let b = a + a;
millstone··on A half-hour to learn Rust
I think both points are right. There's times when it's useful and desirable to be specific about lifetimes, and there's also times where it's annoying noise.

Bignum arithmetic is an example of the latter. You want to just work with numbers, and in Python you can, but in Rust you must clutter your code with lifetimes and borrows and clones.

Swift's plan to allow gradual, opt-in lifetime annotations seems really interesting, if it works.

millstone··on Tesla Short Sellers Lost $38B in 2020 as Stock Surged
Apple Watch and AirPods.
millstone··on Developer progression as a function of navigating complexity
Yeah agreed. Amazon expects everyone to follow their Leadership Principles but no team can succeed if everyone attempts to lead.
millstone··on Developer progression as a function of navigating complexity
How does this work on a team composed exclusively of senior engineers?
millstone··on Writing a custom iterator in modern C++
Yeah, this is a good question. Scott Myers has a talk where he pokes fun at the "guaranteed O(N log N)" sort of a linked list, where the guarantee is in number of comparisons and not the (very large) number of pointer chases.

Why describe at the type level the difference between a backwards pointer chase and a pointer decrement? The hope is: if you know at compile time that your iterator is efficient in this way, you can pick a more specialized algorithm, say, quicksort instead of mergesort. C++ really does enable this at the type level through template specialization. In practice the STL collections haven't lived up to this, and I think the iterator tags are mostly deadweight.

millstone··on Writing a custom iterator in modern C++
This is an interesting point. Walking backwards through a UTF8 byte stream is easy: just look for the next non-continuation byte, and Rust really can do this, though the API is buried under `str.chars().rev()`.

C++ is structured around iterators that point into; this enables e.g. writing into the guts of a std::map but not the guts of a std::string if you care about Unicode, since the write might change the string's byte length.

millstone··on Writing a custom iterator in modern C++
The spec itself defines it as:

Normative for the current edition of the Standard, but having been identified as a candidate for removal from future revisions

This is a very blunt tool. In practice, a feature may be deprecated if it is:

1. Legacy inherited from C that serves no modern purpose. The register keyword.

2. Features hardly anybody implemented. Exported templates is the only example I am aware of. Like falling off the edge of the map.

3. Features that proved to be a bad idea, like incrementing a bool.

4. Features that proved to be wholly inadequate, like codecvt for dealing with Unicode.

5. Features that are reasonably new in C++ but obviated by new stuff. You don't need std::bind if you have lambdas.

This is my outsider's perspective; please chime in if you have standards committee insight.

millstone··on Writing a custom iterator in modern C++
I think you are arguing that iterators are "primarily" for iteration. But in C++ they really are like an abstraction over C pointers. For example, you can hold a std::list::iterator, and use it to efficiently delete from a linked list, without ever iterating.

Sometimes C pointers are used for iteration, but I would not say that is their primary purpose.

millstone··on Writing a custom iterator in modern C++
Iterators are inconsistent, but this plays to the strengths of C++'s duck-typed generics. The same code can either copy or insert, depending on whether you use std::begin or std::back_inserter; this isn't principled but it's powerful.

The "six types of iterators" overstates it. You don't need to sweat those details unless you are writing boost or something. Just add what you need.

I miss C++ iterators in other languages. For example, in Rust it's hard to talk about "a position in a String" which may be advanced or retreated. Usually you give up, use an integer index, and this is much worse.

millstone··on Writing a custom iterator in modern C++
Random access iterators mean you can efficiently advance or retreat an iterator by an arbitrary amount. So a vector (via pointer arithmetic) but not a linked list.
millstone··on A case study on strict null checks
Fair points - Haskell is all-in on these ideas, and agreed that do-notation has power well beyond Result and Option. I regret including do-notation in my critique, maybe list comprehensions instead.

I think we disagree on what "different code" ought to mean. I have a C function which multiplies a list of numbers; I make it immediately `return 0` if it hits zero. In C that's the same function, just optimized; in Haskell it's a breaking API change due to laziness. I suppose the languages reflect that difference.

millstone··on A case study on strict null checks
Yeah, trivial cases are trivial everywhere.

I like your strength/weakness observation. But if you are mutating index variables, you have a hard case, and it probably will be easier to express with a manual loop than trying to shoehorn it into awkward functional constructs.

An example is the "discard elements by a predicate" function, aka Vec::retain in Rust, std::remove in C++. Rust implements this using a for loop. Maybe it can be done with functional constructs, but it would be harder to write and to understand.

https://doc.rust-lang.org/src/alloc/vec.rs.html#1105

millstone··on A case study on strict null checks
A counterpoint: Option and Result are hard to read and unpleasant to work with. They are so annoying, that the language designers extended the language itself to make them tolerable - do notation in Haskell, '?' operator in Rust, guard-let in Swift.

A plain old for loop has so much to recommend it. You get powerful control flow constructs (break/continue/return) and obvious performance characteristics.

Can you tweak your function to stop filling the first time a zero is encountered? That's a simple one-line change with the for loop, but a puzzle for the functional iteration.

millstone··on A Beginner's Garden of Chess Openings (2002)
Chess author Jeremy Silman, who champions the "imbalance" idea, gives a list:

- Minor pieces (bishops vs knights)

- Pawn structure

- Space

- Material

- Files and squares

- Development

- Initiative

I would add how much time is left on the clock, though that is not a feature of the board.

An example: say you have a bishop and your opponent has a knight. This is an imbalance, and you want to exploit it by making your bishop better than their knight. Concretely that means trading pawns, to open up the game, so your bishop can bring its long-range strengths to bear.

millstone··on A Beginner's Garden of Chess Openings (2002)
The "personality" of an opening is the nature of imbalance it creates. For example, in a gambit, white may sacrifice a pawn in exchange for quick development and an attack. In a Dragon opening one side has a powerful bishop but also a potential weakness near their king.

The way you win in chess is to create an imbalance and then exploit your half of it. The imbalance may be on many facets, like different pieces or pawn structure or activity.

Some openings create few imbalances (e.g. Exchange Slav) and these are drawish.

millstone··on A Beginner's Garden of Chess Openings (2002)
Would you mind sharing your rating and what time controls you play?

I am 1930 on lichess blitz (so probably ~1700 FIDE). If I guide the game into lines I know well, I can get both a positional and time advantage since my opponent has to think longer.

millstone··on Silicon Valley exodus: Bay Area tech companies leaving for Texas
I am curious if anyone agrees with my take:

HP Enterprise and Oracle did not move because Texas is "more tech friendly." Instead they moved because HPE and Oracle are no longer primarily tech companies. While they do substantial technical work, most of that will remain in SV.

It's sort of the mirror of Apple, which also has a substantial presence in Austin (finance, etc) but is headquartered in SV because it is primarily a tech company.

millstone··on The YouTube ban is un-American, wrong, and will backfire
This is hyperbole and AOC would be the first to acknowledge it. If "the world will literally end in 12 years" were to take root, then it would be a massive problem for society, not just YouTube.
millstone··on Elon Musk moves to Texas
Worse, if it changes hands through inheritance there is no step up in basis.
millstone··on Porting a 100% local app to the web
The web makes it much easier to give a button a drop shadow than a keyboard shortcut; that's the sense in which it's hard. The web's origin is documents, not software.

"Users don't want websites to override their keyboard shortcuts" is so right and so telling! We've all been burned by copying a Google search link, or had 'automated link attribution' spam our clipboards. Keyboard shortcuts should not be a "power user" feature but that's where we find ourselves, as the web subverts all user interactions.

millstone··on Porting a 100% local app to the web
It's legitimately hard to make a good keyboard shortcut on the web, especially since there's no interop with native keyboard shortcuts (e.g. no web Undo API). This becomes a death spiral: users don't expect keyboard shortcuts to work, so nobody bothers making them.
millstone··on Porting a 100% local app to the web
Keynote actually has pretty great real-time collaboration [1], though it does have more friction than GSlides, not least of which because it requires a Mac.

I agree GSlides has its uses. Web apps are good for ephemeral tasks, but I use desktop apps for stuff I care about.

1: https://support.apple.com/guide/keynote/intro-to-collaborati...

← PreviousPage 5 of 34Next →