Hacker Newsnew | past | comments | ask | show | jobs | submit | Diggsey's commentslogin

> Yes, and the amount of study and knowledge required had a tendency to filter out people with the inclination to do such things. The Venn diagrams weren't completely empty, but they were close, which is why such incidents were rare.

People do exercise their freedom and do terrible things all the time - it's not rare. There are lots of ways to cause harm that don't require any study or knowledge at all, we just seem hyper-focused on the possible "sci-fi" consequences of AI for some reason.

I would argue the reason people don't go and kill someone (or worse...) even more often than they do is not because it's difficult but because most people have no desire to cause that kind of harm, and because of the consequences to themselves of doing so.

So yes: technical difficulty put some kinds of harm out of reach of people, and AI can lower that barrier somewhat, but in the grand scale of "harm people can do" I think it's receiving undue attention.

And from a practical standpoint: how do you get from there to arguing that we should set some impossible-to-define threshold of "frontier" at which point it becomes so evil that we need to forcefully delete it from existence? Don't you see the problem with trying to put such black and white restrictions on something that's so inherently amorphous and slippery? (And by definition, if you delete the "frontier" model from existence then the next best model is now "frontier" ad infinitum...)

On top of that you have the issue that model weights are just information, so in some sense you're legislating the knowledge that is allowed to exist. That's quite a bit more draconian that current laws which usually focus on what knowledge you can share.


You would have had to run `jj edit` in order for this to happen, so I think it's a stretch to say you didn't ask for the edit?

This is the main difference though: in git files can be `staged`, `unstaged` or `committed`, so at any one time there are 3 entire snapshots of the repo "active".

In `jj` there is only one kind of snapshot (a change) and only one is "active" (the current working directory). When you make changes to the working directory you are modifying that "change".

As others have mentioned, the equivalent to `git checkout` would be `jj new`, which ensures a new empty change exists above the one you are checking out, so that any changes you make go into that new change rather than affecting the existing one.


I really, REALLY wish jj picked a different subcommand name for that than 'jj new'.


Thanks for the explanation! I wish I could edit my comment to reflect the truth.


> git was originally implemented as a handful of low level binaries stitched together with shell scripts.

A bunch of low level binaries stitched together with shell scripts is a lot faster than python, so not really sure what the point of this comparison is.

Python is an extremely versatile language, but if what you're doing is computing hashes and diffs, and generally doing entirely CPU-bound work, then it's objectively the wrong tool, unless you can delegate that to a fast, native kernel, in which case you're not actually using Python anymore.


Well, you can and people do use Python to stitch together low level C code. In that sense, you could go the early git approach, but use Python instead of shell as the glue.


Their point was that by offloading the bottlenecks to C, you've essentially conceded that Python isn't fast enough for them, which was the original point made above


Fair point!


Which works for about 5 minutes until someone leaks a manufacturer's private key or extracts it from a device...


Yes this stood out to me as well...


Stored procedures don't eliminate serialization anomalies unless they are run inside a transaction that is itself SERIALIZABLE.

There's essentially no difference between putting the logic in the app vs a stored procedure (other than round trip time)


This is completely untrue. While the index only stores the hashes, the table itself stores the full value and postgres requires both the hash and the full value to match before rejecting the new row. Ie. Duplicate hashes are fine.


For a unique index, that requires a table check, which - IIRC - isn’t implemented during index updates.

The article suggests using a check constraint to get around that - are you saying that does actually check the underlying value when USING HASH is set? If so, I think the docs need updating.


That's super interesting and I am convinced by the dbfiddle but is not very intuitive or well documented? https://www.postgresql.org/docs/current/hash-index.html


This is very good to know because it means this exclusion constraint workaround is a better approach over using a SQL hash function and a btree if you want to enforce uniqueness on values too long for a btree index.


It's also `position: fixed` which breaks all scroll optimizations and makes scrolling feel terrible.


There were two things I think went extremely poorly here:

1) Lack of validation of the configuration file.

Rolling out a config file across the global network every 5 minutes is extremely high risk. Even without hindsight, surely one would see then need for very careful validation of this file before taking on that risk?

There were several things "obviously" wrong with the file that validation should have caught:

- It was much bigger than expected.

- It had duplicate entries.

- Most importantly, when loaded into the FL2 proxy, the proxy would panic on every request. At the very least, part of the validation should involve loading the file into the proxy and serving a request?

2) Very long time to identify and then fix such a critical issue.

I can't understand the complete lack of monitoring or reporting? A panic in Rust code, especially from an unwrap, is the application screaming that there's a logic error! I don't understand how that can be conflated with a DDoS attack. How are your logs not filled with backtraces pointing to the exact "unwrap" in question?

Then, once identified, why was it so hard to revert to a known good version of the configuration file? How did noone foresee the need to roll back this file when designing a feature that deploys a new one globally every 5 minutes?


IMO, safety and "idiomatic-ness" of Rust code are two separate concerns, with the former being easier to automate.

In most C code I've read, the lifetimes of pointers are not that complicated. They can't be that complicated, because complex lifetimes are too error prone without automated checking. That means those lifetimes can be easily expressed.

In that sense, a fairly direct C to Rust translation that doesn't try to generate idomatic Rust, but does accurately encode the lifetimes into the type system (ie. replacing pointers with references and Box) is already a huge safety win, since you gain automatic checking of the rules you were already implicitly following.

Here's an example of the kind of unidiomatic-but-safe Rust code I mean: https://play.rust-lang.org/?version=stable&mode=debug&editio...

If that can be automated (which seems increasingly plausible) then the need to do such a translation incrementally also goes away.

Making it idiomatic would be a case of recognising higher level patterns that couldn't be abstracted away in C, but can be turned into abstractions in Rust, and creating those abstractions. That is a more creative process that would require something like an LLM to drive, but that can be done incrementally, and provides a different kind of value from the basic safety checks.


> In that sense, a fairly direct C to Rust translation that doesn't try to generate idomatic Rust, but does accurately encode the lifetimes into the type system (ie. replacing pointers with references and Box) is already a huge safety win, since you gain automatic checking of the rules you were already implicitly following.

Unfortunately, there's a lot of non-trivial C code that really does not come close to following the rules of existing Safe Rust, even at their least idiomatic. Giving up on idiomaticness can be very helpful at times, but it's far from a silver bullet. For example, much C code that uses "shared mutable" data makes no effort to either follow the constraints of Rust Cell<T> (which, loosely speaking, require get or set operations to be tightly self-contained, where the whole object is accessed in one go) or check for the soundness of ongoing borrows at runtime ala RefCell<T> - the invariants involved are simply implied in the flow of the C code. Such code must be expressed using unsafe in Rust. Even something as simple (to C coders) as a doubly-linked list involves a kind of fancy "static Rc" where two pointers jointly "own" a single list node. Borrowing patterns can be decoupled and/or "branded" in a way that needs "qcell" or the like in Rust, which we still don't really know how to express idiomatically, etc.

This is not to say that you can't translate such patterns to some variety of Rust, but it will be non-trivial and involve some kind of unsafe code.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: