@codesections Thanks for trying it out! It's good to see the shell I wrote being used by others. I've been using it in my day job as my default shell for the last 2 years.
Strange that the shell was taking 100ms to start up for you before. I don't recall this ever being an issue.
We've been adamant about performance since the beginning, but there's still room to grow. There's also room for additional growth in feature set, as well.
The inline syntax and where clause syntax are equivalent means to define the traits of a generic type. The reason that they both exist are because of API readability: sometimes where clauses are easier to read than inline definitions, and vice versa.
The impl Trait syntax was introduced for two reasons: increased readability of APIs when using them for input parameters, and the ability to declare a generic but statically-determined return type that satisfies the trait(s).
The difficult part will actually be learning how to structure complex architectures safely. If you haven't already picked these practices up in other langs, it will be a struggle.
I would advise researching the slotmap, froggy, generational-arena, and slab crates for storing data which can reference each other without lifetimes.
Channels should be used to send events across an application which can be handled in centralized locations. Great for breaking up recursive behaviors.
@musicmatze I've done this in the past with HTTP/s-based RPC, and a work stealer on the daemon which keeps tracks of which WUs have been sent to what client(s). Each WU containing the command(s) to execute on the client, and a deadline for completion. Then each client having its own work-stealer which distributes WUs across threads.
With the new async / await syntax in #Rust, working with futures is easier than ever.
This weekend, I've spent some time rewriting my `async-fetcher` crate with the new syntax. The result is more features, and better performance, at a fraction of the original amount of code.
The new rewrite now supports execution on current-thread runtimes, with optional support for speeding up downloads by using multiple connections to download the same file from multiple URLs.
It's already gained widespread industry adoption across a vast range of fields.
Now that a lot of critical infrastructure, high profile projects, and a good number of applications are being written in it, it's here to stay.
We're using it in all of our projects in Pop!_OS, even for small things, like dynamically-linking custom GTK widgets written in Rust into C applications.
@vancha Naturally, the thing you're not experienced with will always be more difficult to work with than the thing you are experienced with. Spend a few months with it and you'll be doing more in less time with Rust compared to Python.
I generally find Rust to be significantly easier to accomplish tasks with than Python. Be it from no longer having to debug issues at runtime, or from the wide range of high level abstractions missing in Python.
Go does not prevent misuse of types that are being read and written to from multiple threads simultaneously. It's possible for a race condition to occur which leads to UB and crashing of threads.
Rust requires that only one thread may mutate a value at a given time. You're required to place values in locks, or use atomic values, if you want to mutate them in multiple locations across threads.
For single-threaded situations, Rust also provides Cell/RefCell types.
The Go runtime, which goroutines are executed on, is also not optional. It comes with a certain level of overhead over real OS threads, and because the threads maintained by the runtime are spawned before the main function, it's not safe to set up signal handling or forking processes.
In Rust, you can set up any runtime you wish for executing futures, similar to goroutines, but only when you need them. You can even have multiple different kinds of runtimes.
Go allows to send and share types across thread boundaries, even if it is unsafe to do so. Rust uses Send and Sync type markers to prevent this.
Mutex's and other locking types are unsafe due to the separation of data from the lock, as well as lack of lock guards. Requires generics as Rust used.
Atomics support in Go is limited, yet comprehensive in Rust.
Channels in Go are limited because the language lacks support for ADTs (such as Rust enums). This is required for proper event-driven APIs.
@veer66 Happens when there are multiple possible options, but it's easy to give the compiler a nudge.
This is one of the best aspects of Rust, and it's been critical to Rust's success at System76.
I'm constantly refactoring of our projects as they're developed to keep technical debt low, and efficiency high.
Recently, I've spent the last week performing a major refactoring of a GTK receiving application, and each time it's been re-deployed in production, no issues were ever encountered due to it.
As of today, the application is now driven entirely by message-passing. No more use of Rc.
@Pep0ni Personally, as someone with years of experience in both Go and Rust, I would choose Rust for "enterprise software" 10 times out of 10.
Go's error handling and type system is far too leaky, and the concurrency model is horridly flawed.
Rust has proper Send + Sync type markers for validating type usage across thread boundaries, and better threading and concurrency primitives.
System76 Product Engineer; Rust / Linux software developer
Fosstodon is an English speaking Mastodon instance that is open to anyone who is interested in technology; particularly free & open source software.