Live data from Hacker News

Rust RAII is better than the Haskell bracket pattern

snoyman.com

71–80 of 156 posts

Re: Rust RAII is better than the Haskell bracket pattern

#71
post #18

Earlier quoted context omitted.

You can have both, GC, static allocation and RAII, like in Modula-3 for example. Which .NET is finally arriving to, thanks to Midori outcomes. And Java might eventually get there as well, depending on how Project Valhalla ends up. As for languages like Haskell, a mix of bracket and linear types might be the way to go.

I googled "Midori outcomes", but I only found your posts mentioning it. Have a better keyword to search or a link?

http://joeduffyblog.com/2015/11/03/blogging-about-midori/ is a good set of articles about the Midori project.

Re: Rust RAII is better than the Haskell bracket pattern

#72

Earlier quoted context omitted.

> Oddly, Rust's ownership system really does solve these problems No. Rust's ownership problem solves it for trivial cases, at the cost of making it hard to do other things (such as sharing references past the lifetime of the owner without resorting to Rc or Arc , at which point you don't really have lifetime guarantees anymore). The essential limitation of Rust is that (without resorting to Rc and Arc , which would…

> it is conceptually limited to the equivalent of reference counting with a maximum reference count of 1. This is a thing people say, but I think it's misleading. Reference counting can increase the lifetime of an object, but borrowing cannot. I've seen this really trip up beginners. > This inherent limitation makes a lot of things hard It can make them different , which can be hard, but these things are already hard…

> This is a thing people say, but I think it's misleading. Reference counting can increase the lifetime of an object, but borrowing cannot. I've seen this really trip up beginners.

"With a maximum reference count of 1." As the reference count becomes 1 upon object creation, it cannot really be increased further. Hence, only operations that keep the (virtual) reference count at 1 or reduce it to 0 are allowed.

My point here is that you inherently cannot do things where you cannot prove that this virtual reference count can be capped at 1.

Re: Rust RAII is better than the Haskell bracket pattern

#73
post #53

Earlier quoted context omitted.

Oddly, Rust's ownership system really does solve these problems, and Non-lexical lifetimes should eliminate accidental scope-broadening. Unless you are doing some mega-schenanigans, an e.g. MutexGuard gets released precisely when you think. Your point about this being difficult to solve in the general case is true, it's just worth pointing out Rust intends to do that hard thing anyway.

> Oddly, Rust's ownership system really does solve these problems No. Rust's ownership problem solves it for trivial cases, at the cost of making it hard to do other things (such as sharing references past the lifetime of the owner without resorting to Rc or Arc , at which point you don't really have lifetime guarantees anymore). The essential limitation of Rust is that (without resorting to Rc and Arc , which would…

> Rust's ownership problem solves it for trivial cases, at the cost of making it hard to do other things

Your analysis of the trade offs is fine, but you claim that Rust only solves this problem for "trivial" cases. If that's true, then most of the Rust code I've written is trivial. To me, that pretty thoroughly weakens your dismissal here, at least in my case.

Re: Rust RAII is better than the Haskell bracket pattern

#74
post #18

Earlier quoted context omitted.

You can have both, GC, static allocation and RAII, like in Modula-3 for example. Which .NET is finally arriving to, thanks to Midori outcomes. And Java might eventually get there as well, depending on how Project Valhalla ends up. As for languages like Haskell, a mix of bracket and linear types might be the way to go.

I googled "Midori outcomes", but I only found your posts mentioning it. Have a better keyword to search or a link?

It is a path to enlightenment with multiple stops. :)

Start with Joe Duffy blog posts about Midori architecture.

http://joeduffyblog.com/2015/11/03/blogging-about-midori/

Then hop on to his talks.

"Safe Systems Programming in C# and .NET"

https://www.infoq.com/presentations/csharp-systems-programmi...

"RustConf 2017 - Closing Keynote: Safe Systems Software and the Future of Computing by Joe Duffy"

https://www.youtube.com/watch?v=EVm938gMWl0

Then you can watch "Inside .NET Native" from Channel 9

https://channel9.msdn.com/Shows/Going+Deep/Inside-NET-Native

Finally there are the specs and related discussions that lead up to C# 7.3 design.

https://github.com/dotnet/corefxlab/tree/master/docs/specs

The TL;DR; version, basically async/await, the UWP AOT compiler, improved handling of value types, spans (aka slices), improved GC (TryStartNoGCRegion()) have their roots in System C# used in Midori.

Also there are some influences of Singularity, namely Bartok and MDIL, on the WP 8.x AOT compiler, but that is not longer relevant.

Re: Rust RAII is better than the Haskell bracket pattern

#75
post #53

Earlier quoted context omitted.

Oddly, Rust's ownership system really does solve these problems, and Non-lexical lifetimes should eliminate accidental scope-broadening. Unless you are doing some mega-schenanigans, an e.g. MutexGuard gets released precisely when you think. Your point about this being difficult to solve in the general case is true, it's just worth pointing out Rust intends to do that hard thing anyway.

Non-lexical lifetimes do not affect something that implements Drop, so the MutexGuard will, by default, last till the end of its lexical scope. You can still call drop on it manually to release it earlier, though.

Huh! Learn something new every day -- so are lifetimes still exactly describing when things get dropped? And anything implementing Drop just doesn't get optimized lifetimes?

Re: Rust RAII is better than the Haskell bracket pattern

#76

Earlier quoted context omitted.

> it is conceptually limited to the equivalent of reference counting with a maximum reference count of 1. This is a thing people say, but I think it's misleading. Reference counting can increase the lifetime of an object, but borrowing cannot. I've seen this really trip up beginners. > This inherent limitation makes a lot of things hard It can make them different , which can be hard, but these things are already hard…

> This is a thing people say, but I think it's misleading. Reference counting can increase the lifetime of an object, but borrowing cannot. I've seen this really trip up beginners. "With a maximum reference count of 1." As the reference count becomes 1 upon object creation, it cannot really be increased further. Hence, only operations that keep the (virtual) reference count at 1 or reduce it to 0 are allowed. My poin…

That doesn't change much; the point is that (in many languages), variables going into or out of scopes don't fiddle with the ref count[1], and so people assume that something will live until they make the count go down explicitly.

It also only refers to ownership, not borrowing, and both are equally important.

Beyond that, what I'm saying is something more meta: It doesn't really matter if this analogy is spot-on or not; it's got enough wiggle room in it that I've seen it trip up beginners. Maybe that's because they misunderstand the analogy, but given that its point is to convey understanding, that means that it isn't a great analogy, in my experience. YMMV.

1: directly, of course; this also depends on the language.

Re: Rust RAII is better than the Haskell bracket pattern

#77
post #75

Earlier quoted context omitted.

Non-lexical lifetimes do not affect something that implements Drop, so the MutexGuard will, by default, last till the end of its lexical scope. You can still call drop on it manually to release it earlier, though.

Huh! Learn something new every day -- so are lifetimes still exactly describing when things get dropped? And anything implementing Drop just doesn't get optimized lifetimes?

> so are lifetimes still exactly describing when things get dropped?

It depends on exactly what you mean by this.

In a nutshell, "non-lexical lifetimes" means "things go out of scope when after their last use. Drop implies a use at the end of the current lexical scope."

Dropping Drop types earlier ("eager drop") was desired, but has significant problems, including "a large body of unsafe code exists in production which relies on knowing when Drop types go out of scope and changing this behavior may cause a ton of unsoundness in existing code."

Re: Rust RAII is better than the Haskell bracket pattern

#78

Earlier quoted context omitted.

> Oddly, Rust's ownership system really does solve these problems No. Rust's ownership problem solves it for trivial cases, at the cost of making it hard to do other things (such as sharing references past the lifetime of the owner without resorting to Rc or Arc , at which point you don't really have lifetime guarantees anymore). The essential limitation of Rust is that (without resorting to Rc and Arc , which would…

> Rust's ownership problem solves it for trivial cases, at the cost of making it hard to do other things Your analysis of the trade offs is fine, but you claim that Rust only solves this problem for "trivial" cases. If that's true, then most of the Rust code I've written is trivial. To me, that pretty thoroughly weakens your dismissal here, at least in my case.

I am talking about just using basic references & borrowing. Once you introduce reference counting (Rc and Arc) and copying, you open up a lot more options, of course, but at this point you also can't make any lifetime guarantees anymore, because objects can escape the "owner's" scope at will.

Re: Rust RAII is better than the Haskell bracket pattern

#79
post #2

The thing is that, in Haskell, even when you attach a function to run during destruction, the runtime doesn't guarantee that the function will be called promptly, or even at all. Rust drops (runs destructor and deallocates) values as soon as they go out of scope; C++ too. In Haskell you depend on the whims of the GC, which makes RAII unusable. (The Haskell approach of not guaranteeing destructors being called does ha…

> when many C++ and Rust programs are about to end, they spend the last few cycles uselessly deallocating memory that would've immediately been freed via _exit(2) thank god they do this. how many times did I have to manually force linux to release sockets because badly coded C programs which opened sockets forgot to release them causing them to hang up for ~5 minutes after the process ended. With proper RAII classes…

Does _exit wipe out memory or just mark some regions as free ? asking for security purposes.

Re: Rust RAII is better than the Haskell bracket pattern

#80
post #74

Earlier quoted context omitted.

I googled "Midori outcomes", but I only found your posts mentioning it. Have a better keyword to search or a link?

It is a path to enlightenment with multiple stops. :) Start with Joe Duffy blog posts about Midori architecture. http://joeduffyblog.com/2015/11/03/blogging-about-midori/ Then hop on to his talks. "Safe Systems Programming in C# and .NET" https://www.infoq.com/presentations/csharp-systems-programmi... "RustConf 2017 - Closing Keynote: Safe Systems Software and the Future of Computing by Joe Duffy" https://www.youtube…

Ah, so you meant the standard innovations that came out of Midori. I thought you were talking about some new abstraction I hadn't heard of called "outcomes". ¯\_(ツ)_/¯
Post reply on HN