Live data from Hacker News

The Rust I wanted had no future

graydon2.dreamwidth.org

451–460 of 523 posts

Re: The Rust I wanted had no future

#451

Earlier quoted context omitted.

Not knowing about function coloring is a stupid dream and has terrible implications on the performance of your code, which is infinitely more important than you losing 2 minutes having to figure out that you really want to `runBlocking { callThatBlocksForADamnLongTime() }`. The insight that function coloring gives you is terribly important. Roman Elizarov (of Jetbrains, author of Kotlin and lead on Kotlin Coroutines)…

Async doesn't solve that problem. What you're asking for is some sort of expression in the type system of expected performance, but there's no tech that can do this. Consider that modern NVMe SSDs can do disk reads faster than many calculations over the content of what was just read. A function that changes its algorithm to have worse time complexity won't be marked as async but could break your app, adding a single…

This is a perfect solution fallacy. Yes, "whether this function will suspend (and shift execution onto a different thread)" does not tell you absolutely everything about that function. But it tells you things that are worth knowing, that you want to be visible (not super intrusive, but visible) in your IDE. And in a language with a decent type system the cost is pretty small; functions that are agnostic about whether they will run as async can and should simply be polymorphic in async-ness.

Re: The Rust I wanted had no future

#452
post #448
post #439

Earlier quoted context omitted.

>Are you saying that Rust will refuse to compile code that does not explicitly Depends what you mean by explicit. Look at it like this: pub fn main() { let mut vec : Vec = vec![]; let x = vec.pop(); println!("{:?}",x); // prints: None } In this case you see the value is missing. vec.pop().expect("I want a value") will panic with "I want a value" because value is empty. And most rigorous way to deal with it is: if let…

for some reason I can not answer your subsequent reply so I do it here: I looked at your example and played a bit with it and yes I agree with you - compiler does help in this case. My old text: So instead of checking if vector is not empty you check that the return result is not empty. I do not see much difference. If Rust compiler would choke when "else" clause in your example is not present I would understand your…

`x`, the value of the Vector access, only exists within the context of the first block. It does not exist in any other scope. This makes it impossible to access when the result is not valid.

> If Rust compiler would choke when "else" clause in your example is not present

The compiler won't choke, but it will stop you from accessing the value.

It doesn't matter if you omit the `else` clause or not, the type system ensures that you can't access invalid values.

Here's a bit of an example based off of @Ygg2's code: https://play.rust-lang.org/?version=stable&mode=debug&editio...

Re: The Rust I wanted had no future

#453

Earlier quoted context omitted.

Perhaps you'd be interested in Inko ( https://inko-lang.org/ ). It's obviously not there yet in terms of tooling and what not, but it might scratch an itch for those looking for something a bit like Rust, but easier to use. Disclaimer: I'm the author of said language :)

Lots of languages are aiming for "like Rust, but easier to use" -- I think I could name half a dozen. It's a laudable goal! I'm curious how references in your language work. I see the very small example, but it doesn't explain much. Some questions in that regard: Is `&T` a type? Can you store it in a structure, or return it? Can you have a reference to a reference? If you can have a function `f(&T, &T) -> &T`, how do…

If you scroll past the code examples, there are a few more details, though for more you'll need to look at the documentation (specifically https://docs.inko-lang.org/manual/main/getting-started/memor...).

> Is `&T` a type?

Inko's syntax for references is `ref T` for immutable references/borrows, and `mut T` for mutable ones. Unlike Rust, you can't implement methods/traits _only_ for references, instead you can only implement them for the underlying "base" type. So `impl ToString for String { ... }` is valid, but `impl ToString for ref String { ... }` isn't.

> Can you store it in a structure, or return it?

Yes.

> Can you have a reference to a reference?

No, `ref ref T` is "collapsed" into just `ref T`, and the language has no notion of pointers and pointer-pointers.

> If you can have a function `f(&T, &T) -> &T`, how do you distinguish whether the reference it returns lives as long as the first or second argument

Inko doesn't have a borrow checker, so it doesn't. Instead it relies on runtime reference counting to prevent dropping of values that still have references to them. Over time I hope to implement more compile-time analysis to reduce this cost as much as possible, but borrow checking/lifetime analysis like Rust isn't something Inko will have.

Or to put it differently, I want the compiler to catch say 80-90% of the obvious "this ref outlives its pointee" errors without complicated borrow checkers. For the remaining 10-20% the runtime check should suffice.

Re: The Rust I wanted had no future

#454
post #6

Very interesting insight from Graydon, in hindsight I too would have loved something more towards ML than C++. I never liked the kitchen sink approach that I see first C++, now Rust moving towards, but I respect what Rust has managed to solidify into. It's a good language. That said, I still hate async with a passion, it makes the language more complex and not very elegant (i.e. function coloring). And now that I kno…

> a zero-cost abstraction It's just an abstraction, it's not zero-(runtime)-cost. It might be the "lowest possible cost", still nonzero.

A zero cost abstraction is just an abstraction you couldn’t write any better yourself, not one that is actually free. If you’re lookint for an item in a hashmap, you still have to pay the cost of looking up the key. The promise of zero-cost abstractions is that you’re paying the lowest possible cost to do that, with a nice interface that you didn’t have to write from scratch.

Re: The Rust I wanted had no future

#455

Earlier quoted context omitted.

It's important to note that JS has an unfair advantage in that if you want to write code that runs on the universal platform, you're forced to use either it or something that transpiles to it. Python reached where it was on merits alone. (That said, JS is actually a very versatile and almost-great language, getting better all the time)

Python reached where it is because university CS programs which had previously been teaching Java reached for a new language.

Most universities I knew were still teaching Java well into python's rise to popularity a decade ago. Python got where it is by focusing on being simple, easy, and nice to use. Seriously take a look at PEP-20 sometime:

https://peps.python.org/pep-0020/

Things like "There should be one-- and preferably only one --obvious way to do it." just was such a breath of fresh air in language design.

Re: The Rust I wanted had no future

#456
post #261
post #6

Very interesting insight from Graydon, in hindsight I too would have loved something more towards ML than C++. I never liked the kitchen sink approach that I see first C++, now Rust moving towards, but I respect what Rust has managed to solidify into. It's a good language. That said, I still hate async with a passion, it makes the language more complex and not very elegant (i.e. function coloring). And now that I kno…

It's crazy that the programming community even accepted the concept of async/await as a sane one. Being sync or async is essentially a property of the attention of the caller, not of the action itself. Is "eating a donut" a sync or async action? If I'm focusing all my attention on it, essentially putting all tasks aside (after) - then it's a synchronous action. If I'm reading a book/watching a video/walking/etc, whil…

Does blocking I/O or not is very much a property of the function itself, as is "may finish up running on a different thread from the one it started on" (or, if you prefer, "needs to be run under a runtime that provides that capability").

Sending a letter and getting a reply is an inherently async action; you can stare at the mailbox all day but you probably don't want to. Waiting in line at the bank is inherently sync; if you try to do something else and then come back they'll make you start over again.

Re: The Rust I wanted had no future

#457
post #61
post #6

Very interesting insight from Graydon, in hindsight I too would have loved something more towards ML than C++. I never liked the kitchen sink approach that I see first C++, now Rust moving towards, but I respect what Rust has managed to solidify into. It's a good language. That said, I still hate async with a passion, it makes the language more complex and not very elegant (i.e. function coloring). And now that I kno…

That being said... python had a BDFL and look how that turned out. I think designing and evolving any living programming language is just one of the hardest problems out there. Incredible blog post indeed, was awesome to read it.

Python took a clear turn for the worse when it stopped following the BDFL model.

Re: The Rust I wanted had no future

#458

Earlier quoted context omitted.

> a zero-cost abstraction It's just an abstraction, it's not zero-(runtime)-cost. It might be the "lowest possible cost", still nonzero.

A zero cost abstraction is just an abstraction you couldn’t write any better yourself, not one that is actually free. If you’re lookint for an item in a hashmap, you still have to pay the cost of looking up the key. The promise of zero-cost abstractions is that you’re paying the lowest possible cost to do that, with a nice interface that you didn’t have to write from scratch.

Agreed, that's why I said might. Whether rust async is the best possible abstraction probably depends on the event loop, and your code. I could be wrong but I think if you write a trivial async function it will still have spinach for the async even if there are no yield points and it's effectively a non async function

Re: The Rust I wanted had no future

#459
post #412
post #261

Earlier quoted context omitted.

It's crazy that the programming community even accepted the concept of async/await as a sane one. Being sync or async is essentially a property of the attention of the caller, not of the action itself. Is "eating a donut" a sync or async action? If I'm focusing all my attention on it, essentially putting all tasks aside (after) - then it's a synchronous action. If I'm reading a book/watching a video/walking/etc, whil…

This was my first (and obviously wrong) mental model of how async works. There are functions, you can call them sync or async if they handle IO or UI or they will get a necessary data later. I still don't understand why I can't fetch a URL from top level javascript. Also I don't understand why zig async and await passes the control flow that seemingly total arbitrary way. The naive approach (put async calls in a queu…

> I still don't understand why I can't fetch a URL from top level javascript.

> Maybe javascript async is build upon regular promises and regular objects, instead as a proper language element with proper support in the javascript engines?

Yes, they are promises.

> The async and await keywords enable asynchronous, promise-based behavior to be written in a cleaner style, avoiding the need to explicitly configure promise chains.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

> The naive approach (put async calls in a queue, and periodically check if they are completed or can be executed) seems fast, deterministic, and good enough in every way? Okay, maybe zig needs the speed, and can't just stop the execution of the sync code time to time to do something else, but why javascript?

You're describing preemptive multitasking. You can create separate execution threads pretty easily in most languages (even super old C code), but that's not why Javascript and Zig have the 'async' keyword. The difficult part isn't the asynchronous execution; the hard part is handling the result from asynchronous code (i.e. the 'await' part). Promises are a simple mental model for organizing how pieces of code depend on the results of other pieces of code. The C# documentation does a good job explaining this:

https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous...

Note: From Zig's documentation it sounds like 'async' is cooperative multitasking. This is single-threaded execution. It is "concurrent" code, but it isn't executing in "parallel".

Concurrency is difficult because it is explicitly resource management. You don't need concurrency for calculating the correct answer, you only need it for managing time.

Re: The Rust I wanted had no future

#460
post #326
post #310

> I was weirdly focused on [the Actor] model that in practice has many issues I maintain the actor model is probably the most theoretically perfect concurrency and distributed computing model. The holy grail. We just don't have the right hardware for it and it's extremely limited by addressability issues with current technology. So I don't really find this surprising, nor disagreeable. It's just not a model that Work…

I'm not sure I agree. Runtimes like Erlang's work great for many things. You just have to be aware that actors aren't going to magically get you more CPU cores — i.e. you can have as many IO-bound actors as you want; but a CPU-bound actor (done correctly, such that "gets out of the way" of actor scheduling) is just a regular CPU-bound preemptive OS thread; and you can only realistically have as many of those as you h…

> and you can only realistically have as many of those as you have CPU cores in your machine, before you start experiencing highly degraded performance.

Which is precisely why I stated that they're the best model theoretically that simply do not work on our current technology.

I don't think a language solves things. It's a fundamental shortcoming of our technologies, routing topologies, etc.

Post reply on HN