I (along with a few others) started a project about 20 years ago, inspired by things like the STEPS project at VPRI, HyperCard, and similar things, to build a new kind of desktop environment. We wanted to move away from applications as an abstraction and provide documents and tools for manipulating documents. We wanted something that respected Raskin’s First Law, so there would be no save button. Documents (including their editing history) were automatically persisted, the user abstractions were not save (losing data should be explicit, retaining it should not), but ‘tag’ and ‘export’. The former associates some metadata with a revision so that you can find it later. The latter converts the document into some form for external interoperability (e.g. in a video editing app, the internal representation would be raw footage and transforms but export might give you an MPEG-4 video file).
This required a uniform object model that different components could interoperate with it and end-user programming tools that made it easy to write custom tools that operated over the data. This is where I started down a rabbit hole that ended with my building hardware. Current MMU-based isolation is inadequate for this. I wanted users to be able to write code in safe (and easy!) languages that could use existing libraries. Unlike STEPS, I have no interest in rewriting libavcodec in a DSL so that it fits in my 20KLoC budget for the system, I want to just use it without worrying about whether it’s memory safe and, if I use it so wrongly that it crashes, get a recoverable error (restarting the library instance is fine). I joined a project that has the skeleton of the things I wanted and evolved it to the point where it did everything I needed: I could write managed-language code with object-granularity interop with C/C++ and have strong guarantees that the C/C++ could not violate type safety for my code, now all I needed was to get it into mass production.
That’s basically what I’ve been working on since 2017 (though also on some other relevant bits). $1bn would be sufficient to stop waiting for Arm to find a customer willing to say that they’ll buy a large quantity of chips if CHERI makes it into the architecture and just tape out my own moderately competent 64-bit RISC-V core with a licensed GPU and other bits and still have a couple of hundred million left over for the software work.
For those wondering about Etoile, it is Data Object system, something like HyperCard++.
I’ve been a fan of Etoile ever since I read about it on HN at least a decade ago. I have Raskin’s book on my shelf because of it. It’s so nice to to see you frequent Lobsters
I have been thinking about what a “HyperCard” for the Web looks like that removes machine and OS boundaries so you are fully immersed in data and projections of that data. I think LLMs will provide that bijective lens between graphical programming and having a concrete text representation.
I think your vision is within reach using technologies available right now, Wasm, WebRTC, WebSockets, WebGPU.
There are zillions of modern HyperCard analogs. For example, Decker , which can be run online: https://beyondloom.com/decker/tour.html
I could write managed-language code with object-granularity interop with C/C++ and have strong guarantees that the C/C++ could not violate type safety for my code, now all I needed was to get it into mass production.
Any pointers on this? I don’t see it on the page
FWIW “mycpp” from https://www.oilshell.org/ has some properties like this. We write in typed Python, translate it to garbage-collected C++, and a normal Ninja build system composes it with hand-written C++. There is very little wrapping due to the “syntactic puns”.
There are some issues regarding typedef and integer sizes, but since Unix was pretty much written with int
, it doesn’t seem to be a problem in practice.
Making your own chips would be a very good use of $1 billion :-)
I don’t think I could spend $1 billion, though I could certainly spend $10 million
At $1 billion you run into management problems. Now everyone wants your $1 B :)
edit: Is it https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/201404-eurosys2014-tesla.pdf ? At first glance it doesn’t seem like a managed language
I’m somewhat familiar with Capsicum from many years ago, but haven’t followed the rest of the work
CHERI is not a managed language, it is a hardware design for a CPU that can dynamically ensure memory safety in code compiled from C and other unsafe system languages (C++,Rust,Zig). This can make it safe for a managed language to depend on C library dependencies. I suspect that some additional software components are needed for a complete solution.
Obviously they lacked most all safety guarantees, but this reminds me very much of some of the OpenDoc demos from the 1990s, conceptually.
The author of redpanda gave a short response on hackernews. One principal point of contention seems to be whether or not it is fair to turn off syncing for kafka.
*fsyncing specifically
And my understanding, which may or may not be right, wasn’t that it’s off or not but whether fsync is in the data write path or if it’s done periodically behind the scenes (even as frequently as every few ms). The idea being you could write data but not fsync so you respond to the user saying the data is written but then the server crashes before the fsync happened (or the kernel flushed the data to disk on its own) so you lost data you told the user you didn’t… And whether or not Kafka’s replication story makes that unlikely or impossible.
My own understanding is that there is no set of APIs, syscalls, incantations, or sacrifices to the gods that will ensure data is actually written to a persistent store. For any given combination of the above, there will always be some “well, technically the operating system/filesystem/drive firmware is allowed to claim it really-actually-really-for-real wrote the data even though it didn’t because it thinks it knows better” loophole, and you will learn about it from someone who makes a condescending “doesn’t anyone read the manual anymore” post in reply to a question about why you lost data.
In the end, even if the kernel really really told the firmware, and the firmware really really told the hardware, and the hardware really really told that one MOSFET to hold that one bit, physics may not comply and the block may arbitrarily become unreadable later.
Durability becomes a game of
And yeah, like you say, remembering that fsync has a lot of confusing sharp edges.
If you know exactly the hardware+software stack you’re deploying to, you may be able to wield fsync with more faith. If you’re building something like Kafka that gets deployed to god knows where, fsync just becomes an API to reduce the probability of data loss on a given block write / disk. You still need to implement the actual safety protocols (eg. using checksumming and replication) on top as if fsync didn’t exist.
No system is perfect, naturally. But we’re talking about a known failure mode (box disappears before fsync) vs a potentially extremely uncommon failure mode (fsync lies).
a potentially extremely uncommon failure mode (fsync lies)
This post is a decent summary of some of the issues. The simple atomic-write pattern described in the first section, for example, requires four fsync
calls which need to be correctly ordered among the other calls.
And even that, as the author points out, is insufficient, because on some popular operating systems/filesystems, fsync
is not guaranteed to actually flush data. And even when fsync
is flushing, the drive firmware still might not actually commit the data to the drive.
People learn this in expensive ways every so often, and when they do articles like the one I linked get trendy on programming forums for a little while, and then everyone mostly forgets and goes back to thinking this is an “extremely uncommon failure mode”.
The simple atomic-write pattern described in the first section, for example, requires four fsync calls which need to be correctly ordered among the other calls.
This example doesn’t look representative of what you’d see in redpanda.
And even when fsync is flushing, the drive firmware still might not actually commit the data to the drive.
For someone’s desktop or whatever, maybe. Cloud providers can, should, and do pick hardware where the drives have an independent battery that flushes the cache on failure. This is verifiable behavior.
I think not calling fsync in a distributed system is one of the only ways to work with the platform rather than against it. In a cloud environment, everything has to go through an extra hop. fsync is the pathological worst thing to do, a byte in user land has to make it all the way to “virtual” committed disk.
You need append only log for your log so you can log while you log. fsync is just an offset into a “file” log. Who says it should be linear? God posix sucks.
Seems like a distraction from the parts where Redpanda performance dramatically degrades after 12 hours, or with a different configuration of writers, or how it fails to achieve (on the same hardware) the purported performance.
Redpanda wrote a blog post specifically discussing fsync - https://redpanda.com/blog/why-fsync-is-needed-for-data-safety-in-kafka-or-non-byzantine-protocols
The article is about subinterpreters, but there is also nogil fork: https://github.com/colesbury/nogil
I looked at this years ago, so. many. global. variables. I can’t imagine how much work this took unless there was a simpler way than putting everything into a Lua style environment struct.
Almost every nontrivial C extension out there has threading bugs that are currently impossible to hit because of the GIL. It will take an enormous amount of effort to make all the old C code thread safe. That means in practice you may not be able to use a lot of useful libraries that rely on C code in a multithreaded python interpreter.
Sure, but this is how we make progress with software:
When I introduced Sidekiq to the Ruby community, there were still lots of gems with threading issues, including Rails itself. Now the ecosystem is thread-safe as Sidekiq usage grew and folks fixed the threading issues. It just takes a few years.
Data races are famously non-deterministic. Your tests will likely pass and you will still release a heisenbug into the wild.
I hate to be that guy who suggests rewriting in rust, but I came to this thread to lament the fact that my current favourite pastime (writing python modules in rust for the enormous performance boost) would be going away.
Maybe though… it wouldn’t be a bad idea?
A lot of these extensions are wrappers for third-party libraries, so what you’d be doing really is rewriting the third-party library and committing to maintain it forever.
Also, it’s not always only C – if you think you can build a better BLAS/LAPACK implementation (required for NumPy) than the current Fortran versions, you’re welcome to try it. But I think there’s a reason why Fortran continues to be the base for that stuff, and it’s not “because they hate Rust”.
A Rust adapter-wrapper from Python to some Rust and some C is still a totally valid pattern where you don’t rewrite the whole stack, but you add some correctness (say parsing, state machines, thorny inplace processing). It can be a spectrum.
A lot of these extensions are wrappers for third-party libraries, so what you’d be doing really is rewriting the third-party library and committing to maintain it forever.
I don’t mean to be glib, but isn’t that a bit of an entitled attitude that places an unfair burden on open-source maintainers? I see no reason that they shouldn’t commit to only maintain it as long as its useful for them. If someone else finds it useful, then they can either pay for support or maintain it themselves.
That’s assuming the Python API even makes that possible. For example the buffers API allows python side to cause data races and Rust can’t prevent that: https://alexgaynor.net/2022/oct/23/buffers-on-the-edge/
Parallelism is not the same as a speed-up. If a task takes 100 CPU seconds with Python, 10 threads/processes with full parallelism means 10 seconds to get a result, and those cores can’t be used for other things. The Rust equivalent might only take 1 CPU second on a single core. In some situations parallelism is good enough, but optimization tends to be much more valuable if you can manage it.
(Longer discussion: https://pythonspeed.com/articles/do-you-need-cluster-or-multiprocessing/)
Rust has a very strong unique ownership model. Python allows arbitrary aliasing. Two Python threads can share any objects that are returned from Rust. I think the only solution to this is to make everything that is exposed to Python adopt the Sync
trait. Anything in Rust that is mutable and Sync
is unsafe
. The simplest way of doing that mostly correctly is to expose Sync
proxies that acquire a lock before calling into the real Rust objects (Rust has some nice lock guard types for doing this, so the unsafe
bit is in the standard library). It’s not clear to me that this would end up being easier than exposing C/C++ things.
Rust’s concurrency benefits rely on the Rust type system. When you are interoperating with code that has weaker constraints then there are lots of places for bugs to sneak in.
Rust Python: https://github.com/RustPython/RustPython
Unless the C code is doing stuff like using OS-level resources assuming there’s only one instance of it running (which is ekhm anyway because there can be multiple CPython processes,) it’s still going to run under GIL within the subinterpreter.
I enjoyed reading this, but Fastly’s Fast Forward provides free CDN services for open source projects which might help with the “most Linux distributions are free and thus don’t have a project budget to spin up a global CDN” problem.
I have no experience of Fast Forward myself, but I’ve heard that OpenStreetMap and meta::cpan have benefited from it, and I’m sure others have too.
Still, running a CDN off repurposed thin clients is very impressive.
It’s also a unknown when Fastly will do a rug-pull and stop supporting Open Source projects with a free CDN, so building your own, as well as using Fastly’s is probably the best way to go.
Hosting files on CloudFlare R2 is 0.015 / gb-month with no egress costs.
https://developers.cloudflare.com/r2/pricing/
I could reasonably see a small homebrew linux distro having 100GB in downloadable assets, that would be 1.5$ a month.
Void recently started offering a Fastly mirror, but I find it slow compared to the other Tier 1 mirrors
Montgomery County, Maryland, US
Checking again, it seems like the issue is that Fastly almost never has anything in cache
Interesting, I know for certain there are some void hosts in that region. Probably need to make sure their mirrors are pointed correctly to warm the cache.
The other term you are looking for is “ambient authority” which also comes the capability model domain.
On mobile and way too long inthe sauna so I can’t think, but you could also have a model parse requests into well formed queries, or produce straight line code that can be checked. Basically the correctness checks should run out of band.
A lot has been written about the downfall of Prolog. As someone who didn’t live that moment but now contributes to Scryer Prolog I think there’s no one reason, but several.
One of the reasons that I do not hear in this kind of posts is the lack of standardization. You didn’t program in Prolog, you programmed in Quintus Prolog, with its dialect (Edimburgh tradition). But you had also Turbo Prolog (now Visual Prolog), Prolog II and Prolog IV from Prologia (the company from Alain), Arity/Prolog32, … and even more academic systems. When ISO Prolog got defined in 1995, it was already too late. If you didn’t hear before about some of those dialects is because they’re effectively dead. The only branch that still receives work is the Edimburgh-ISO family. I think other languages in that era suffered from the same.
It’s funny that the post, in 2010 thinks that Mercury and Oz are more promising than Prolog, because, at least from my perspective, they still have fewer users than Prolog.
It’s funny that the post, in 2010 thinks that Mercury and Oz are more promising than Prolog, because, at least from my perspective, they still have fewer users than Prolog.
I agree, this part has aged least well of the various speculations in there (I wrote the post). In the 2000s it felt like these multiparadigm logic-flavored languages had more excitement behind them than Prolog did, but they didn’t really take off.
One thing that did happen since 2010 is a Datalog revival of sorts, driven by the static analysis community discovering that it’s a nice way to formulate some of the analyses they’re interested in. That’s led to new, fast engines like Soufflé, and a bunch of new users who don’t come from an AI/knowledge-rep background.
Same as Scheme and Lisp.
This is where Java really really shined. You could take some code you found and an implementation and it would mostly just work.
My first k exposures to Scheme was to find some neat library or program, grab a Scheme I could install easily enough and then have it spew stacktraces and cryptic errors. Then reading through the code itself, I could if I was lucky, find out which Scheme they were using. They just assumed you would know which Scheme they were using. It is almost like language designers hate their users and their users hate each other.
One of the reasons that I do not hear in this kind of posts is the lack of standardization. You didn’t program in Prolog, you programmed in Quintus Prolog, with its dialect (Edimburgh tradition). But you had also Turbo Prolog (now Visual Prolog), Prolog II and Prolog IV from Prologia (the company from Alain), Arity/Prolog32, … and even more academic systems.
I had a play with Prolog a few years ago, and not being aware of this up-front caused me great confusion and dismay when even trivial Prolog programs weren’t working on my system …
I don’t know, this seems like a very inside baseball idea of why prolog didn’t take off. I think it’s fundamentally just that network effects exist and it is difficult to bootstrap language uptake when people also need to pay a large learning cost to get in. The only thing I’ve seen in the last decade that actually succeeded in this regard was rust, and that required an unbelievable level of fanatical hype & evangelism to convince people to move off the objectively terrible experience of writing C & C++. But it happened! Thousands upon thousands of people really learned how to write proofs of memory safety.
network effects
Balkanization prevents the network effect from occurring! If Rust pulled a D and had Phobos/Tango, boom, network effect would be destroyed. If Rust had two different backends that were 100% total, the ecosystem would split along which target they were using.
I think the interesting factor here is that Prolog did have massive hype for a while (in the 80s). Much more so than ML-family languages, which then carved out a niche (or several) for themselves.
I would bring up Python and Ruby but they got big more than ten years ago and now I feel old. :)
Edit: and of course they aren’t really applicable examples anyway because both have gentle, not steep, learning curves.
Orange site links
I don’t think the article has legs. It conflates things and really no-one uses MPI directly. MPI and Spark/Hadoop solve totally different problems.
Yeah they did a number on you there because chatGPT is always going to be too expensive. The interesting takeaway is that we are already getting to the point where we can run half decent AI on consumer hardware.
I guess ‘LLM’ scams is too nerdy but how about this: “AI is coming for your bank account” ;)
Yeah, there’s a tradeoff in giving a piece like this a title – does the average reader understand it vs. does it get at the core nugget / idea?
I think one of our main takeaways is that scam followup, not initiation, is now made way easier by conversational LLMs, the fact that they can be run on consumer hardware, and the fact that they confidently BS their way through anything is a feature not a bug.
I was talking to a scammer selling car parts (that they didn’t have) the other day, and it took me five or six emails to realise they were full of shit. My first thought was, man if this were chatGPT I bet I would have wasted a lot more time on it
Exactly, yeah – saves them time, wastes your time, and has a higher chance of success than an unsophisticated scammer.
I was thinking about this – I guess with LLM-based generated text we may no longer be able to distinguish a scam email than a real one. No more PayPall or silly typos. :-)
The silly typos are on purpose to groom their marks. The idiots don’t notice the typos and those are exactly the people they don’t want to target. Chesteron’s Typos.
But the typos are there only because less gullible responders waste scammers’ time. If scamming is automated, they can go after harder-to-scam victims too.
I know you meant “don’t waste”. Yeah the existence of the LLMs mean that an LLM can stalk and customize their attack to the individual prey. Romance scams will rise. They could construct bots to clone the voice of existing phone support people and their methods. World is getting cyberpunk way too quickly.
That “always” is not going to age well. It is already rapidly advancing towards running on cheaper hardware. It’s likely already cheaper for triaging spam responses and followups than manual labor, and is more scalable.
That’s the nuance in the comment and the discussion about the title. ChatGPT is the model by OpenAI. It is expensive not because it requires beefy hardware to run, but because OpenAI can charge whatever they want.
But it’s not the only LLM in town and Facebook’s leaked LLaMA can be run by anyone without paying licensing costs. That’s the cheap LLM for anyone to run, but it’s not ChatGPT.
That’s the nuance in the comment and the discussion about the title. ChatGPT is the model by OpenAI. It is expensive not because it requires beefy hardware to run, but because OpenAI can charge whatever they want.
I can’t share the exact costs, but from what I’ve heard internally, the margins on most of the OpenAI-based products in Azure are much lower than you might expect. These things really are expensive to run (especially if you factor in the amortised cost of the insane cost of training, but even without that the compute costs for each client running inference are pretty large). My cynical side says that this is why Azure is so interested in them: consumer demand for general-purpose compute is not growing that fast, if you can persuade everyone that their business absolutely depends on something that can only run on expensive accelerators then you’ve got a great business model (and, since you’re not using them all of the time, it’s much cheaper to rent time on cloud services than to buy a top-of-the-line NVIDIA GPU for every computer in your org).
Yep. My rumor mill is even more dire; scuttlebutt is that OpenAI is losing money on every query! They’re only accepting the situation because of hopes that the cost of inference (in the cloud) will continue to fall.
I’m surprised they’re already running at a profit! (Unless you mean the margins are an even lower negative than the negative I previously thought they were.)
I’ve tried something similar with PNG by just throwing the lowest bits away in RGB24 mode, but this appears to be much more clever. Question is, is the extra computational power necessary worth it?
On the decoder side it doesn’t matter how it was done, and generally less data is better. If you don’t have limits on the encoding side, then you can make it as complex as you want.
Worth it how?
Existing lossless formats are extremely compute intensive. The author referenced QOI, think of this as in the same vein.
Are you saying that throwing away the lowest bits is easier and achieve the same result, that it doesn’t need the additional complexity (in the authors work) to achieve the result they showed. Without a mathematical comparison between your work and the authors it would be impossible to say if it was worth it.
Worth it how?
Indeed. It would be interesting to compare this to a stupid quantizer like I suggest, combined with zopflipng. The latter is extremely slow. Perhaps we could get the best of both worlds? Would this be worthwhile compared to just using JPEG with full chroma and quality >= 90?
Existing lossless formats are extremely compute intensive
Not really, unless you’re talking about lossless JPEG2000 Part 1. I work with decoding intra-only video in a broadcast context, where files are often 4k or 8k with 48 bits per pixel at 50 Hz or so, regularly above 1 Gbps, sometimes as high as 5 Gbps. Here decoding performance becomes an issue, especially for Part 1 files. Amusingly QOI is likely much too slow for this use case due to its serial nature.
These new formats don’t appear to be designed to solve any actual industry issue. No one cares about a format’s spec fitting on a single page.
Someone at work used ChatGPT to generate some code for doing interrupt handling of floating point registers. It was subtlely wrong. At first glance it looked correct, but upon closer inspection it has a bug that, if not fixed, would cause confounding errors in ways that are incredibly hard to track down. It is the kind of error that corrupts data and would show up far away (in space and time) from the actual problem. In other words, a nightmare bug.
The generated code would save no time here. You still have to go read the spec and understand how everything works to ensure that the code is doing the right thing. That’s where all the work is.
I still find the ‘it’s great for boilerplate’ claim in the article depressing (though true). If a large language model has enough data points to sample that it can fill in what you want by making some tiny tweaks to something it’s seen in thousands of examples, why do you need that in your source code? Whether a human or an algorithm write the code, humans still have to understand and maintain it, so the cost is still there (if anything, being able to write it more easily makes it easier to write larger, and less maintainable, codebases). It really shows how far we still have to go in producing usable programming languages and frameworks.
I heard the ‘great for boilerplate’ part often enough that I figured I’d test it a while back, based on an acquaintance of mine’s observation that ChatGPT can come up with remarkably correct code when asked for a minimal IIO driver. A device driver for a somewhat obscure Linux kernel subsystem seemed like a good test case for that – it’s something I’m familiar with, something I also had to implement in alternative ways, and also there’s a lot of boilerplate involved, at several levels, from “this is a Linux module” to “this is an SPI device attached to this interface” to “this is an IIO driver which will present values on these channels”.
Thing is, most of that is “true” boilerplate only for simple devices. All those innards are exposed primarily in order to support more advanced use cases, like sharing device driver code between multiple variants of the same device (e.g. same ADC with different channel counts and sampling frequencies) or allowing the programmer to enforce things that the hardware expects to be enforced at the other side of the bus (e.g. no new requests while the hardware is working on another request, minimum time between consecutive requests etc.).
For the most simple of devices, you don’t really care about any of that, and you’re left with boilerplate you copy-paste around – something you could, indeed, presumably tuck under a generic “make me an IIO driver” language macro, or a generic IIO device driver that you just hand off a pair of read, write functions to.
For more advanced devices, though, all that is “just” initialization logic, not generic boilerplate. Where one ends and where the other begins is hard to say. For every step in a more advanced driver, I can sigh and think you know, I wish this was just a config parameter somewhere. But a config definition format that can really describe all these quirks would just be a really awkward DSL with imperative features. We all know how that goes.
Thing is, ChatGPT is great at the former kind of boilerplate, but years away from the latter. If I ask for a minimal IIO driver, it gives me one (literally one that just probes but, hey, I did ask for a minimal one). If I ask for a minimal IIO driver for an SPI device, it gives me one that just probes, but also reads and writes some junk on the SPI bus (which it doesn’t use in any way). By the time we get to specific things, like write me an IIO driver for this particular device attached via this particular interface, ChatGPT comes up with “boilerplate” that’s loosely related to the prompt but otherwise firmly into well, at least it compiles land – it writes made-up values at made-up addresses, sometimes on made-up buses. (This isn’t unexpected, and is obviously an artefact of training data availability: if I ask for the driver for a device that’s already supported in the kernel, it basically just give me the existing driver code, minus the license :-P).
Linux is probably not the pinnacle of solid, reusable kernel frameworks, but it makes a trade-off that’s familiar to all of us – it trades verbose, but mostly default code for simple cases, in order to make it less painful to allow customization for more advanced cases. ChatGPT is overwhelmingly biased towards the former because they are bound to be more represented in its training data and because it’s inherently better at generating that kind of data. However, that’s not necessarily representative of what a human programmer needs.
If a large language model has enough data points to sample that it can fill in what you want by making some tiny tweaks to something it’s seen in thousands of examples, why do you need that in your source code?
I think the same thing, and it’s also why I don’t consider it all that impressive. If it’s generating boilerplate, why is that code required in the first place?
I needed to write a thing to turn a 1D array into an N-dimensional array two days ago. I tried Googling “golang N-D array” but couldn’t find it. So then I tried Googling Python N-D array and got solutions that were the opposite of what I wanted (going from N-D to 1) or just 1 to 2-D. So I tried asking ChatGPT to do it in Python and it gave me a good solution, and then I asked it to translate it to Go, and it did a good job. Maybe the code has a subtle bug I haven’t noticed yet, but it probably cut 2 hours of noodling with a pen and paper down to half an hour of searching and reviewing.
Here’s the version after I cleaned it up by making it generic and removing an unneeded else branch:
func inflate[T any](lst []T, shape []ArrayDimension) any {
if len(shape) == 1 {
return lst
}
dimSize := shape[0]
dimShape := shape[1:]
result := make([]any, dimSize.Length)
sublistSize := len(lst) / int(dimSize.Length)
for i := 0; i < int(dimSize.Length); i++ {
startIdx := i * sublistSize
endIdx := (i + 1) * sublistSize
result[i] = inflate(lst[startIdx:endIdx], dimShape)
}
return result
}
This is pretty much the ideal use for ChatGPT because it really is just a semantic search of existing code. I would have been just as happy if Google had given me the webpage of someone else writing out the algorithm, but since a keyword based search can’t distinguish converting 1 to N from N to 1, Google-style search failed.
looks like this function is broken if len(shape) == 0 or if the lst doesn’t contain the exact number of necessary items
why your function isn’t defined as
func inflate[T any](lst []T, shape []int) any {
....
}
There’s an outer function that calls the inflate function after checking the size is correct. I don’t want to repeat the check on every step of the inflation. See https://github.com/jackc/pgx/pull/1511/files
Someone at work used ChatGPT to generate some code for doing interrupt handling of floating point registers.
Ouch. That is also the last thing an LLM should be used for. One could potentially use it to generate test cases. The future in this area is to have an LLM connected to a theorem prover so that the output can be checked.
A friend that works in internet infrastructure said that using third party DNS (like google DNS, for instance) almost invariably makes things slower, because your ISP DNS will always be closer, and likely have smaller load.
Anyone knowledgeable on the subject cares to weigh in? Does this has the same issue?
There are multiple layers to that. And it’s not true that they are always slower.
First of all a lot of them are fast, especially if they are popular and cache everything. So they don’t have to query upstream.
Google, etc. put DNS caches into Internet Exchanges and ISP data centers. So they may be just as close.
Sadly some ISPs have badly configured DNS servers.
But the speed part is typically blown out of proportion, because things you use will likely be cached at least once on your system. Most OSs ship with a local caching DNS server (or a library doing that) and even browser cache DNS records.
So in the end it rarely even matters. If you have an application where it would matter, you’d likely make sure things are cached. closed. So you probably only care if you somehow have an application where you query a lot of different hosts basically all the time. Other than maybe running a crawler or something I can’t really imagine many application. And even then you probably don’t care if the first request to a host takes milliseconds longer, potentially.
Reasons to care are when your ISP’s DNS server is badly maintained, does some sort of censorship, doesn’t offer features you want to use, etc. The big browsers will use DNS over HTTPS with a pre-defined server, so skip your OS/DHCP setting altogether, unless you manually change it.
In terms of security I am unsure whom to trust more. Some big corporation that might be a juicy target, where probably a lot of people interact with it, but which might have good policies, or a small one that anyways is able to track which IPs you connect to. The other side of security is around encryption.
I am on century link, the only DNS server they can run is into the ground. CloudFlare and Google area always faster and more reliable.
I am calling it now - algebraic effects are the “next big thing.” The syntax for it in OCaml 5 is a little clunky, precisely because there’s actually not much syntactic support for it yet and it’s just implemented as a library. But, if you look at languages like Eff or Koka where the syntax is more integrated, the whole concept is very lightweight and solves a ton of problems.
Nitpick: I call them “effect handlers” rather than “algebraic effects”. “handlers” emphasizes the key property of effects, which is that you define their behavior (in the handler) separately from where you use them (in the handlee). And it suggests that they generalize exceptions (exceptions handlers), which is correct. On the other hand, the “algebraic” in “algebraic effect” comes from looking at equations expected to be satisfied by handlers, it is an idea that is important/influential in the theoretical circles that invented effect handlers, but it is in fact completely absent from the realization in practical programming languages, that generally cannot check that equations/laws actually hold.
(For monads, the community has realized that laws are important and that checking them, even on the nose, is useful. Maybe such a time will come with effect handlers as well. Note that non-free monads also quotient over some equations, so we don’t actually need explicit reasoning to enforce equations.)
I hear your point. I like to minimize the division between theory and practice, because I don’t really see them as different things. Algebraic effects are so useful exactly because of their algebraic properties, not in spite of them. The fact that those properties aren’t checked for in implementations is only relevant to me in the sense that implementations should make sure to follow the theory.
So coming up with a different name is an admission that they are separate things, which I don’t think they should be.
The fact that those properties aren’t checked for in implementations is only relevant to me in the sense that implementations should make sure to follow the theory.
It’s arguably worse than not checking the equations. There is no way to specify in the language what the equations should be. For monads and applicative functors (or other standard algebraic structures), the set of expected laws is fixed once and forall by the structure. For algebraic effects, each effect signature will naturally come with its own equations. Some signatures (Get,Set for example; or free monads) have a standard set of equations that would be expected, but many use of effect handlers in language that support them are for bespoke effect signatures where no one has tried to think about the expected equations.
Dependently-typed languages with a notion of quotient (or higher inductive types, etc.) give a natural way for the user to express equations – and to prove that they hold. Combined with effect handlers, you can work with “algebraic” effects. But without those… We could do with in-language support for equivalence assertions, that we could try to check dynamically for example. But OCaml, Koka don’t have those either.
This is a great nit to pick and I learned a lot from your comment. Eff wasn’t familiar to me before now so thanks for exposing me to that as well. Regarding your remark about integrated syntax, are there any examples of syntax which make writing effect handlers particularly ergonomic?
I think Eff has the most minimal syntax. Here’s an example with printing, which for example would be done using Monads in Haskell:
handle
perform (Print "A");
with
| effect (Print msg) k ->
perform (Print ("I see you tried to print " ^ msg ^ ". Not so fast!\n"))
;;
You can see more examples here: https://www.eff-lang.org/try/
I think people have been saying algebraic effects are the “next big thing” for a number of years now.
What would be the advantages of multi core ocaml over say rust? Does ocaml have a non-garbage collected lifetimes based form of memory management?
What would be the advantages of multi core ocaml over say rust?
OCaml’s compile speed blows Rust out of the water. Incremental development and edit-compile cycles are way shorter. Makes it much easier to try out code changes. Oh, and OCaml actually has a pretty good REPL which can conveniently load your working project and let you interactively explore it.
I don’t see them as incompatible or only currently slightly competing because of implementation details. Rust has a solid enough footing that other languages should start to have a Rust runtime or core. OCaml on Rust would get you the best of both worlds.
It would also require a hard dependency on the LLVM and Rust toolchains to bootstrap, which would add a huge amount of complexity.
Which is why Rust needs to have a non-LLVM bootstrap path. LLVM is too big to fail at this point, or too big to compile, or both.
I’d like to see a boostrap path that goes through Wasm where we could bootstrap the whole ecosystem in under 1MLOC.
Does ocaml have a non-garbage collected lifetimes based form of memory management?
No. But there’s, of course, no silver bullet. So non-garbage collected lifetimes as a memory management is not for everyone.
What would be the advantages of multi core ocaml over say rust?
That you don’t have to use Rust, and you get effects handlers, and OCaml’s type system.
OCaml has a fantastic formal methods ecosystem, e.g. WhyML.
Since it’s more of a high-level language, verified code is simpler to achieve.
In what way is Ocaml directly related to WhyML?
Stating the obvious: Drop the “Why” and the “Oca” and you have “ML” in both.
But, re-stating some info from the Why3 page:
A user can write WhyML programs directly and get correct-by-construction OCaml programs through an automated extraction mechanism.
Many proof assistants support extraction, often to OCaml. Extraction is pretty much never a verified process though, mostly because OCaml doesn’t have a formal semantics, so it can’t be verified. So I wouldn’t say that OCaml has a “formal methods ecosystem.”
I agree that OCaml’s formal methods tools could be improved (languages like C or Ada have a better story), but I think you are unfair. WhyML was explicitly designed as a subset/dialect of OCaml amenable to formal verification, and feels very close to (imperative) OCaml programming – see Camleer as a tool to bridge the gap, without strong formal guarantees but it works nice in practice. So yeah, I would say that they are “strongly related”.
This being said, I also expect the verification tools for Rust to improve quickly, for example Creusot which is itself built on top of Why3 is rather impressive. Unfortunately the elephant in the room is unsafe
: some Rust codebases will be amenable to formal verification, but I would suspect that a lot of Rust code in practice depends on unsafe to deeply for this to really work on everyday programs. In practice people that have verification in mind may end up designing projects from the start in “safe Rust” with, say, a non-standard library ecosystem.
I agree that they’re related, but I guess my point is that the whole ML family of languages is related in that sense. OCaml can surely be part of a formal ecosystm - in fact I intend on using a verified interpreter in OCaml for my own language project that I’m working on. So I’m being a bit pedantic - the verification isn’t done on OCaml itself, but rather OCaml is the final result of a verified project.
Yes but the verification is done in WhyML, and there is no formal verification of the extraction process.
I have nothing against extraction. My point was that there is no real formal methods ecosystem for OCaml, and that verification is done in other languages.
Extraction works well enough in practice. I mentioned this elsewhere in the thread, but I’m planning on using extraction to create a verified interpreter for a language project I’m working on.
As far was what my preferred alternative is, I am partial to model-based test case generation. At least at some point in the workflow, because there is always a point past which there are no formal semantics so you can’t even do true verification. And even if there were, testing is a lower-cost investment.
It’s important to clarify what seems to have happened, for people not as familiar with how alternative package indexes work in Python:
--extra-index-url
argument to pip
to specify their package index.--extra-index-url
, pip
will use the extra URL, but only as a fallback for packages that it doesn’t find on the main public Python Package Index. Packages that exist on the main public PyPI will be installed from the main public PyPI (presumably the nightly builds of PyTorch are names or versions that don’t exist on PyPI, so the PyTorch package will come from their index and not PyPI).torchtriton
that they had only uploaded to their own index, and that they had not uploaded to the main public Python Package Index.torchtriton
to the main public Python Package Index, and that was the ballgame – pip
would always find the one on the main PyPI first, and not fall back to PyTorch’s “extra” package index.This is why:
--extra-index-url
is always something to do with caution.--extra-index-url
should make sure they register/upload “dummy” packages matching their private package names to PyPI.The better alternative to --extra-index-url
, incidentally, is to have the alternative index be a mirroring index combining the public PyPI’s packages and the extra private packages you want to host. Then you can pass --index-url
(note: no “extra” there!) and have pip
use your alternative index for all packages, rather than go back and forth between multiple indexes.
Many tools can serve as mirroring indexes to fulfill this use case. I have used and liked devpi for this in the past.
Thanks for the devpi tip. I don’t have anything that currently does this, but I’ve used --extra-index-url
this way before without the precaution of registering dummy names.
At around 4:40pm GMT on December 30 (Friday), we learned about a malicious dependency package (torchtriton) that was uploaded to the Python Package Index (PyPI) code repository with the same package name as the one we ship on the PyTorch nightly package index. Since the PyPI index takes precedence, this malicious package was being installed instead of the version from our official repository.
sigh Why didn’t anyone think of this attack vector till now?
That attack vector has been live for decades, on multiple systems. Someone attacked a Seattle startup using leaked internal package names at least 8 years ago.
Luckily, Python 3 releases are fairly backwards compatible. …
A symptom of a bigger problemThe need to upgrade is not a one-time event, it’s an ongoing requirement: … If you’re still on Python 3.7, that is a symptom you are suffering from an organizational problem
One could argue that the “bigger problem” here is actually that it’s not possible in-principle to write software in Python today (or for many popular platforms) that will definitely still work on a system with security patches five years from now.
i.e. If you want to write software that is “finished”, as I often do as a person who wants to start the occasional new project and doesn’t have quadratic time to spend on maintenance, your options are very limited.
Python sometimes deprecates and removes things even within a major release series, and of course some people dislike that, though I find it’s pretty minor myself.
But I’d argue that it’s much more of a problem – speaking as a maintainer of open-source code – that some people think they can just call their software “finished”.
What you’re actually doing in that case is demanding that I (and every other maintainer of something your “finished” software depends on) promise to provide bug fix and security support to you and your users, from now until the heat death of the universe, and also never do feature releases again because your users might be tempted into upgrading and then your software might not be “finished” anymore.
And… I won’t even quote you a price on that; it’s a complete non-starter. If you want maintenance of your dependencies past the period the upstream provides (and in the case of Python it’s five years for each minor/feature release), you can do it yourself or find someone willing and pay them whatever they charge for the service.
Of course I’m not expecting that a giant list of dependencies will be perpetually updated for me. But if I write a simple utility with no dependencies other than the language runtime, then yeah, that should be finished. I shouldn’t need to add it to an ever-growing list of “things I maintain now until I die”, and neither should you.
You don’t owe me any particular kind of maintenance, and I don’t owe you any particular kind of maintenance. This is all gratis; we’re all doing it for fun or because we care about it or because we think it will get us a job.
For what it’s worth, Rust has solved this problem, as far as I’m concerned, with Rust Editions. It’s not impossible; it doesn’t require an ongoing sisyphean effort performed for free.
But if I write a simple utility with no dependencies other than the language runtime, then yeah, that should be finished
Python has a clear support policy: feature releases get five years. If you want to declare your software “finished”, then in at most five years it will no longer be receiving bugfix and security support of the platform it runs on.
Meanwhile I’m not super optimistic about Rust having solved this “problem”. The language is still extremely young and they’re accumulating a lot of “we promise to keep this working for you forever” stuff that I think is not sustainable over the kinds of time horizons the “finished software” people will want.
(my own stance is that the only way software can be “finished” is when it’s no longer used by anyone, anywhere, and never will be again)
the only way software can be “finished” is when it’s no longer used by anyone, anywhere, and never will be again
This is trivially false if your software is running in an environment where it doesn’t have to care about security. I can run just about any unmodified video game ROM from the 80s on my laptop using an emulator. There’s no inherent difference between a video game emulator and a language implementation - the difference is that one of them is “retrocomputing” and the other is “general-purpose programming”. Rust editions are essentially cutting “retrocomputing releases”. Python could do the same, or someone else could do so (and some have built 2.7 forks, to much gnashing of teeth)
Note that virtually every C compiler can still compile code from the nineties (that’s thirty years ago) using options like --std=c89
. The same is true for Common Lisp, although that’s not an evolving standard like C is. Fortran compilers can compile code from the seventies…
But for modern languages it’s sort of acceptable to not have backwards compatibility. Of course, backwards compatibility also has a flip side in that it means every bad decision must be kept around forever (although it can be deprecated or even dropped in newer “modes” of course).
The aggressive breakage is makework. My tolerance for that varies greatly based on the season I’m in. But, if I’ve marked something finished and it must be updated to support Critical Business Functions, that’s where support contracts come in.
(I suppose I’m not quite compatible with open source still.)
You can run unmodified Python code on your laptop too. You just have to run it in a VM that has a compatible Python interpreter for it to run. That is essentially the same thing you are doing when you run your 80’s ROMs on an emulator. You are handling the maintenance of getting that ROM to work by changing the environment around it to suit it, the same thing you’d have to do with the old Python code.
In the same vein as another reply: you’re relying on the emulator being maintained, in the same way you’re relying on a specific version of the Python interpreter to be maintained. You’re also relying on the games not having any show-stopping bugs in them, because the original vendor is long past the point of fixing them.
So no matter how you choose to phrase it, yes, you really are relying on others to do long-term maintenance on your behalf as part of your ’finished” software.
Trying to think here if your problem needs to be solved at the language level, or at the packaging level. Would you be happy if there was a tool that could package your code + dependencies + any version of the python interpreter into a binary? Then, as long as the code, the packaging tool, and the pinned version of your dependencies were available, anyone could package it from source.
This only moves the problem, of course, because such a tool doesn’t exist. But other languages have similar problems: I doubt you can run ruby or php from 10 years ago in the latest version with zero hiccups.
This only moves the problem, of course, because such a tool doesn’t exist
You can do this easily without any involvement of the language or the packaging level with any virtualization/containerization tool.
There are also quite a few tools that do more like you suggest of producing a “binary installer” type distribution – off the top of my head: PyOxidizer, PyInstaller, and py2exe are all alternatives in that space, but I know there are some others, too.
This is why I usually target apps whatever Python interpreter current Ubuntu LTS ships with, so it will be working for a long time for a lot of people.
The solution is to ship your own python interpreter with your application or to achieve the same effect, containerize it.
I would really like this more flexible language for setting breakpoints. For example:
One way to accomplish this is by setting breakpoints that create or disable other breakpoints. That sounds tricky though. I’d rather think of it as a single breakpoint with a (complex) condition.
Is there any tool that does this? Maybe a gdb plugin?
GDB is programmable with Python, when a breakpoint fired, it could walk the stack and if not part of the monitored code, it could continue.
I’d create a universal standard for electrical mesh networking in order to create a fully distributed power grid. Buy a solar panel, plug it into the grid. I wouldn’t need centralized crypto ledgers for the payment. Each vertex in the graph would know how much it had sent/received. Since we’re talking about physical connections here, you could just meter it and bill using normal wire transfers using traditional banking. If a node ended up with an unpaid balance, it would just be automatically disconnected or de-prioritized.
I really want a world where rather than power outlets we have Universal Power Transfer sockets. You buy a solar panel and just plug it in. You buy a battery and just plug it in. You have a laptop? Just plug it in. No thought to it what-so-ever, no electrician needed. Just consumer distributed grid power.
If I wasn’t so obsessed with consumer distributed grid power, I’d create a stenotype system with electromagnets which would allow you to read using the keyboard (like that the keys would move). I’ve already developed a low power prototype. I don’t use electromagnets to actuate the keys (that takes too much electricity and is too bulky), instead I use electromagnets to hold the keys down. You can press down all the keys and then the computer can allow some to pop up, showing you the word. Pressing the word down again causes the next word to pop up. Stenotype reading is going to be super weird, I think that it is fundamentally strange that you would read with the same exact neurological pathways that you used to write. It might also be useful for blind people, but I’m mostly curious about how it would feel myself.
I like the power grid idea, could also work for load regulation, community priorities (pumping water, greenhouse lights, cpap machines).
As for your stenotypereader, I could see a chorded keyboard that maybe buzzed each key. But if you found a cheaper way to build braille displays into the homerow on a keyboard. Then you could read while you type!
Neat chorded Braille display http://cecitech.com/en/?product=esys12-braille-display
*edit, this is neat project https://hackaday.io/project/12442-molbed-modular-low-cost-braille-electronic-display
I spent a couple of years researching assistive technology (I was at one point working on the keyboard idea pretty seriously) and I think that buzzing won’t work. There were a number of non-piezo braille display prototypes that were cheaper or displayed multiple rows of characters and a major reason for the failure of new tech is that visually impaired people really hate noisy displays. Having the user provide the energy to press the key down, and then having a tiny electro magnet hold it down until it is released is quiet and it is also extremely low energy (allowing for battery powered use. It also allows the user to regulate the speed of character change, simply by pressing the keys that pop up down again.