The new implementation calls a closure and waits for the threads when that closure returns. Unlike the destructor here's no way to stop that code from running when it should.
1,881 karma · joined December 10, 2017
The new implementation calls a closure and waits for the threads when that closure returns. Unlike the destructor here's no way to stop that code from running when it should.
I wouldn't say it changes very fast. If you look at the language features in the past two releases they're all of the form "allow {existing feature} to do {thing you'd expect to be allowed}", and the library additions are minor.
But it changes often, every six weeks, where e.g. Python releases features only once a year. And it's common practice to install new releases as soon as they come out without waiting for distros to pick them up. That means software starts depending on new features in minor frivolous ways that nevertheless break the build for older Rust versions.
I make an effort to have my libraries support older Rust releases, but I have to go out of my way to check for compatibility. Not everybody does that, and it's unrealistic to expect everyone to—but with a different release schedule that would give fewer issues.
>>> {1} | {1.0} | {True}
{1}
But the behavior for dicts is surprising even in that light: >>> {1: 1} | {1.0: 1.0} | {True: True}
{1: True}Here's a Rust fuzzing story from yesterday: https://hacks.mozilla.org/2022/06/fuzzing-rust-minidump-for-...
It claims that Rust is particularly suitable for it because integer overflow panics in debug builds (and out of bounds indexing always panics), which sounds reasonable.
The effect might be positive or negative depending on the circumstances.
JavaScript doesn't do this, you can replace properties of window at will. I don't think Ruby does it, or Lua. PHP probably does it under some circumstances in modern versions but only because it's remarkably un-dynamic for an interpreted language.
This is normal fare for high-level interpreted languages, for better or worse.
It's not easy, even in a few hundred lines I had to remove many conveniences to go that far back, but it's very legible. The compiler has my back, I'm never confused about whose fault it is.
Rust is young, but I don't expect this to be any different in 2030.
That stance is very much real, even if it's best described by gesturing at half a dozen examples. And it's nothing new, really. It's just Worse is Better all over again. I think it's instructive to see how it plays out in Go.
This rant is one-sided, but it doesn't pretend to be otherwise.
I use Rust and like it well enough but it's amazing that its amount of complexity can work at all. It's healthy to have a counterpoint that stays clear even of generics.
My thinking is that that API has to distinguish between many strictly defined error codes, while anyhow homogenizes errors and focuses on human-readable information. How would you tell whether an anyhow::Error means EINVAL or EFAULT?
It's the same fundamental design tradeoff that makes it unsuitable for Rust libraries, even if anyhow wouldn't be visible in the public API.
> The uuid crate can be modified to support the kernel infrastructure as its backend
Fair enough, using a modified version seems reasonable.
Linux has its own UUID infrastructure, so it seems weird to pull in a whole parallel implementation. At the very least you'd want to disable all the generation code, and it's unclear to me if the uuid crate supports that.
rand is large. Does Linux need all the probability distributions it supports? (ripgrepping for "Bernoulli" only turns up the name of a floppy disk system, so probably not.) Doesn't it already have an implementation for the ones it does need?
parallel:
for i in 0..<n:
spawn times_i(v, u, i, n, reverse)
(https://github.com/hanabi1224/Programming-Language-Benchmark...)It's almost four times as slow as the otherwise identical single-threaded version.
(The thread points out that the Nim version uses a doubly-linked list from the standard library while you'd need unsafe in Rust, and the lru crate does indeed use unsafe. So take that into account.)
I'm sure it's possible to cut it more. It'll never be tiny, but it can be smaller than it is now.
On my system it manages 20GB/s vs 6 GB/s (piping through pv into /dev/null).
That doesn't seem so bad, the GNU coreutils Debian package has an Installed-Size of 17.9MB. Though there might be hidden drawbacks I don't know about.
It's a lovely library. Generated help text with colors and line wrapping based on your terminal width, informative error messages that suggest corrections for typos, and a declarative model that lets you express subtle relationships between options. You don't get that from getopt.
But it's also pretty large. https://github.com/rust-cli/argparse-benchmarks-rs has some numbers.
(Disclaimer: I wrote one of the competitors on that page, lexopt. But I also use clap, depending on the project, and I'm happy with it.)
It would be worse if it touched the bytecode itself, I've seen that break even in a bugfix release.
It actually works in PyPy (if you change the way dictionaries are merged so that it's 3.8-compatible). Other Python implementations could have a harder time.
A future Python release could always overhaul the bytecode system to the point this no longer makes sense. I think they'd consider it a backward compatibility break, but I'm not sure, and Python makes those fairly regularly regardless.
If the optimization were added to the standard library then it could just be kept in sync with the interpreter.
The oldest commit is from 2013. Rust hadn't hit 1.0 yet, Go only barely.
And I have a PR to fix problems in another Rust wrapper of the same libc functions: https://github.com/uutils/coreutils/pull/2653
It's hard to get right. Skimming the PR, the feedback looks reasonable.
I think shellcheck is the best argument against this. POSIX shell is just stuffed to the brim with weird gotchas, places where the obvious way to write something causes subtle bugs down the line.
It's the only programming language I use that feels adversarial, where you have to be paranoid to properly solve simple tasks. (Admittedly some of that is because of the reliance on system programs rather than the shell language itself.)
Everything's passed by reference, so the list has to contain pointers even if you know all its elements have the same type. And some objects can change their type by assigning to __class__, which can happen from a distance (because everything is by reference).
A careful implementation can solve this for some builtin types. PyPy does it for ints: if a list only contains ints it's represented as a proper numeric array. But then as soon as you append some other type the whole list is converted to a more expensive more traditional representation.
PyPy's ints still have to pretend to be heap-allocated objects at all times. In particular they have to do something tricky with the id() function, which on CPython just returns an object's memory address. The return value has to be unique and consistent for as long as an object lives.
You can do this in Rust, up to a point. There's a lint to ban dangerous arithmetic: https://rust-lang.github.io/rust-clippy/master/index.html#in... . You can then use the {saturating,wrapping,checked,overflowing}_{add,div,mul,abs,...}() methods to decide exactly what should happen on overflow.
But WUFFS seems a lot nicer. Judging by the README it first tries to determine whether overflow is actually possible, while Clippy will happily forbid you from running "1 + 1".
subprocess.run_escaped("tac -- %s | grep 1 > %s", "foo.txt", "bar.txt")
over this: with open("bar.txt", "w") as outfile:
tac = subprocess.Popen(["tac", "--", "foo.txt"], stdout=subprocess.PIPE)
grep = subprocess.Popen(["grep", "1"], stdin=tac.stdout, stdout=outfile)
tac.wait()
grep.wait()
(In practice the shell grammar is so grotesque that I'd never trust it to be 100% correct. But the idea is nice.)Does CC BY-NC actually do this? As far as I can tell it only really talks about sharing/reproducing, not using.
Or is the only thing prohibiting other commercial use the words "available for non-commercial use only"?
I think you only need homomorphic encryption if the transformation is something that the owner of data can't or shouldn't do themselves. It would be overkill for simple financial information.
They tried that, but they failed because they didn't know that it's possible to downcast from an interface.
It's really hard to have that kind of problem in a dumb REST API. `return {"name": record.name}` does what it says with hardly any magic. But if I write `return record` there's a whole extra layer that grabs information out of record, and I have to trust that it only grabs the information I want it to grab.
This is not to say that dumb REST APIs are definitely better. Having to do things manually also introduces risks.