What you're suggesting seems like a spectacular leap.
I do not think it is very likely that the unnamed employee at Cloudflare that was micro-optimising code in the DNS resolver is also the author of this RFC, Joe Abley (the current Director of Engineering at the company, and formerly Director of DNS Operations at ICANN).
This is interesting.
It looks like there was even some discussion of making this behaviour part of the standard, since it's implemented by all of the major browsers.
It works for any type that implements the `std::error::Error` trait; which is something you can easily implement for your own types.
If you want your errors to be integers for some reason, you can wrap that type in a zero-sized "newtype" wrapper, and implement `Error` for that.
The Stack Overflow answer you linked seems to be claiming that it's simply easier to return strings, but I wouldn't say this is a restriction imposed by the language.
Much easier than implementing the error interface in go.
Rust is powerful enough to allow macros to remove annoying boiler-plate, and so most people using rust will grab one of the error-handling crates that are de-facto standard and remove the minor pain you're talking about.
In go, it's not really possible to do this because the language doesn't provide such macros (i.e. the old third-party github.com/pkg/errors wanted you to implement 'Cause', but couldn't provide sugar like 'this-error' does for it because go is simply less powerful).
I've found implementing errors in go to be much more error-prone and painful than in rust, and that's not to mention every function returning untyped errors, meaning I have no clue what callers should check for and handle new errors I add.
Let's look at a common example: you want to return two different types of errors and have the caller distinguish between them. Let me show it to you in rust and go.
What's the difference between importing some hundred's of lines from thiserror in rust vs importing the "error" package in go?
If the difference is just "It's okay to use stdlib code, but not dependencies", then go's a great language by that metric.
I don't think that's what matters at all. What matters is the abstraction that the programmer deals with.
In go, the abstraction I deal with, as a programmer, is what I showed above.
In rust, the abstraction I deal with is also what I showed above. One of those things is simpler.
Further, the abstraction in go is leakier. My function returns a 'error' interface even if it can only be those two concrete types, so the caller of my function has to step into my function, reason through it to figure out all the error variants, and then check them with 'errors.Is' or such, and changes to what variants are returned aren't statically checked.
In rust, I can look at the type-signature, write a 'match' statement, and never have to manually figure out all the variants returned, since the compiler just knows.
My point here is that what matters is the abstraction that programmers interact with. Third party libraries are bad when they give a leaky abstraction that causes the programmer pain. Standard libraries likewise.
In this case, the abstraction available in rust is cleaner and requires less code for me, the user of the package, so I don't think the lines of code used to build that abstraction matter.
I addressed that with the start of my comment: "Let's look at a common example: you want to return two different types of errors and have the caller distinguish between them"
Yes, your example implements the error interface, but it's not realistic. There is real go code that does that, but that's the reason I have to do string-matching type error handling in go, and frankly it's an argument against the language that its error handling is such a mess that some people see that as reasonable.
Having code that does
return errorString("You have to do string matching on me internal error")
is something you can do, sure, but it's not good code. Idiomatically in go, it would also be "errors.New", not this errorString type you made.
In rust, that would also be just as easy since it would be:
bail!("oh no internal error")
using anyhow, which is the de-facto standard way to do crappy string-style erroring, like the above.
But that's not what I want to talk about since that sort of error handling isn't interesting in either language, and isn't where they differ.
> In this case, the abstraction available in rust is cleaner and requires less code for me, the user of the package, so I don't think the lines of code used to build that abstraction matter.
> Why do you see this as something that matters?
It's true that the abstraction in rust has more code underlying it, but why does that matter?
If you de-facto never have to implement the rust error trait by hand due to excellent library support, then it's a moot point, isn't it?
Anyway, my examples above did implement the error trait, simply by deriving it.
> Are you unable to just write Rust without importing something?
Rust does have less in the stdlib, yes. If you want a json serializer in go, that's the stdlib. In rust, it's the serde package.
Rust is intentionally a smaller standard library. I don't think there's anything wrong with that, and I personally prefer it since it allows for more innovation on things like http / json / error interfaces / etc.
I don't know why you're phrasing it like it's a bad thing.
Thats a good outlook. Dont worry about any problem, just import something an its fixed! More imports the better! Hopefully we can do away with all code, and just import everything.
Well, before Go 1.13 came out, every decent production codebase in Go had to import Dave Cheney's pkg/errors[1] unless you totally gave up the idea of having useful error traces.
Go 1.13 has incorporated most of what this package does into the standard library. It really doesn't matter much whether the code is in a de-facto standard package or folded into the standard library IMHO, but Rust could do the same.
Rust did partially do this; one of the previous generation of packages here, failure, had most of its ideas eventually rolled into std::errror::Error, which enabled this next generation of packages (anyhow, thiserror, miette, eyre... the only one I'm not sure about is snafu, which did exist before, but I'm not sure if it got more improvements due to these changes or not.)
> Dont worry about any problem, just import something an its fixed! More imports the better!
We're talking about error boilerplate here.
Just as I do not write assembly by hand, but instead let the compiler generate that, just as I don't write http clients by hand, but let someone else do that, yes I would also rather not write error boilerplate by hand.
I would love it if I didn't have to write as much code to solve problems, but I recognize that the problems I'm solving are mostly specific enough that they require bespoke code specialized to the problem space.
However, error handling? Yeah, I don't care to hand-write that.
Said less glibly, I will happily import stuff when it makes my life easier, and write it myself when that is better.
You're absolutely right about implementing the `Error` trait yourself in Rust, it's a pain! And with many things, the Rust team felt it was better to leave error experimentation to an external library, as the community can iterate more quickly and settle on a favorite. At the moment, that favorite is `thiserror` (for defining errors in a library) and `anyhow` (for working with errors in application code)
That's been a pretty common pattern in Rust - leave some less clear parts of the standard library out for external crates to implement and experiment on. So you'll see almost all big Rust projects use one of those error handling libraries. You _could_ implement it with just the standard library, but you're just giving yourself more work for little to no gain.
Here's an example without using external libraries:
Not particularly good or bad (and I didn't even replicate all the functionality that `thiserror` gives you).
So yeah, Go and Rust have different philosophies for their standard library, and you can argue about which is better, but I don't think one can be proved objectively better than the other.
The Rust code is doing much more than what the Go code is doing, it's making more incorrect cases impossible. I really don't understand the complaint about imports. Anything that's not built into the standard library is not valid somehow? I'm struggling to imagine what would make someone think this.
I found this[0] discussion on Jonathon Blow's youtube channel about game physics/framerate dependence. It certainly seems to more than simply a problem of software architecture as some commenters appear to suggesting here.
> I just realized I’m agreeing with a social justice warrior about something
Why are you accusing thinkxl of being a “social justice warrior” and why, exactly do you feel that that undermines your agreement? Is website usability a liberal ideology?
Lacking any actual justification your edit feels very out of place on hn.
Actually, I was referring to https://sonniesedge.co.uk/posts/progressive-enhancement, who literally self-identifies as a "whiney SJW feminist fuck" in the first paragraph. And it's less "undermines my agreement" and more "Eww, I'm on the same side of this argument as such-and-such evil person; please don't assume this means I agree with them about anything else.". I'd go back and clarify, but the edit window is over.
2^64 nanoseconds is > 580 years. Even cutting it in half for signed values is still likely 10X the expected lifetime of this particular iteration of APFS.
The granularity is probably useful for establishing an ordering (even somewhat arbitrarily) for highly concurrent file system operations, and thus potentially skipping a bunch of expensive synchronization.
Found this: https://github.com/jbenet/nanotime. No idea if related in any way or used for APFS but it was interesting enough for a quick read. This one is MIT licensed. A little more searching I found a variant but it's done with big-endian so it's much different.
I have the same issue on the mid 2012 13" model. The camera seems to stop being recognised whenever the macbook goes into sleep mode... no solution found so far.
It's really annoying and reminds me of Windows where such issues were routine and rebooting was not a big deal. I moved to a Mac to get away from such issues, and largely have, except this one niggling issue.