unquabain.com
Medium humanoid creature, lawful/liberal
Speed: 30 ft.
Languages: Common, Latin, Go, Ruby, Rust, Python, French
Ben was female at conception, just like all human beings.
He makes music and digital art sometimes. He used to be @querulus.
301 posts
118 followers
311 following
Regular Contributor
Active Commenter
comment in response to
post
Einstein hasn’t been wrong yet. (Except about that one thing, but we ignore that.)
comment in response to
post
This kind of "vitalism" stuff is also straight out of the fascist playbook man
comment in response to
post
Are we fighting with clubs and sticks?
comment in response to
post
I want to like this skeet, but I can’t mess with this.
comment in response to
post
When the poor say “don’t treat marginalized individuals like they are inferior” that’s “the woke mind virus”, but the rich can literally edit the language of textbooks to remove references to people and events, and that’s okay.
comment in response to
post
That is why, when the rich get tax breaks and subsidies written into law, it’s “free market”, but when the poor collectively decide we don’t want to shop at openly bigoted stores it’s “cancel culture”.
comment in response to
post
How about, maybe contrived:
let x = {
let mut unlocked = mtx
.unlock()
.unwrap() // runtime panic maybe
// do some fancy stuff
let tempVar = unlocked.clone();
// more fancy stuff
tempVar;
}
sendOutside(json!(x)); // sends “{}”
comment in response to
post
But then all that goodwill toward Rust goes out the window when I remember its semi-implicit returns. A nearly-invisible little ; can make or break your program.
comment in response to
post
So Rust picking one and enforcing it makes a certain sense, even if inevitably I dislike some of the particulars of that choice (why is transferring ownership between scopes the default, but retaining it requires athletic punctuation characters?)
comment in response to
post
But that’s a common-sense development discipline. And in the end, the problem with dynamic memory management in C is not that it’s hard—it’s incredibly simple: there are only two rules—it’s that there are a zillion “right” ways to do it. The problem is documentation and communication.
comment in response to
post
Then, either the methods of Widget that have privileged access to gg have to check for nil, or geegaw’s own methods do; dealer’s choice.
comment in response to
post
That is, assume
type Widget struct {
gg *geegaw
}
where geegaw is some unexported type. You want the zero-value of Widget to be usable, so the nil value of geegaw should be valid, but you keep that internal to your package.
comment in response to
post
Not that I’ve run across. I would say, though I can’t recall seeing this in any formal documentation, that it’s a technique you should reserve for unexported types so that your exported types can be created by consumers of your interface like
w := &Widget{}
comment in response to
post
But, on the topic of “footguns”, unlike Rust, there’s nothing about a *Widget that says “in this case, for this type, nil is meaningful”. It’s not self-documenting like Option<&T>
comment in response to
post
Yeah, basically. Or not even assume that the caller has checked, but rather assume that no value of type (*Widget) has ever been nil, since it probably started out life as a “local” variable at some level of the stack.
There’s no reason for it to be nil unless someone has explicitly made it nil.
comment in response to
post
So in practice, you don’t check method receivers against nil unless you’re using nil as a valid value. BUT you do do a LOT of checking errors against nil.
comment in response to
post
That said, Go’s error handling (or conspicuous lack of it) gets tedious.
w, err := AWidgetProbably()
if err != nil {
// what do you do here?
}
Mostly you wind up just decorating and returning the error, making a glorified, manual stack trace.
comment in response to
post
Where you run into trouble is if you’ve got a function that returns a pointer and an error, and you lazily ignore the error.
w, _ := AWidgetProbably()
w.Foo()
But that’s, I mean, you’re asking for it there.
comment in response to
post
A principle in Go development is that the zero-value of every type should be meaningful. (Go initializes every variable, including pointers, to 0.) So you really only encounter nil if nil has some meaning, in which case, of course you check for it, if it’s a valid value.
comment in response to
post
Yes and no.
All memory is owned by the garbage collector. So you can do, and often do, something like this:
func NewWidget() * Widget {
return &Widget{}
}
Of course, if you’ve been recently programming in C, that’ll make your teeth fall out.
But you’ll probably never see
var ptr *Widget
comment in response to
post
The same for the dev, I mean. Obviously Go’s big nanny runtime verses Rust’s big nanny compiler is a real distinction, and a valid reason for choosing one tool rather than the other for a specific project.
comment in response to
post
ANYWAY, this is down to a matter of opinion. In my opinion, relying on the standard library check if a reference is nil and starting a catchable panic is exactly identical to having the runtime do the exact same thing, because the boilerplate code to avoid that is trivial in either case.
comment in response to
post
Basically, all the compile-time footguns which are supposed to prevent runtime footguns mask this particular runtime footgun.
comment in response to
post
…inexperienced dev going around removing muts from variables they write to once and adding lifetime annotations to structs to answer a question that has only one possible answer, not to mention hunting down all the hidden mut refs they didn’t know they were borrowing.
comment in response to
post
A tiny bit of effort that is equivalent to the effort of checking for nil that an experienced developer will do out of habit and a new developer may not know to do.
Maybe if .unwrap() were the only bit if extra busywork Rust had you do, then it would make a difference, but Rust has the poor…