• 0 Posts
  • 24 Comments
Joined 1 year ago
cake
Cake day: June 15th, 2023

help-circle



  • Visual Studio Code with rust-analyzer has all the features I would expect from an IDE. I mean, rust-analyzer works together with cargo, so refactoring over file boundaries is not an issue. Visual Studio Code has built-in support for debugging and source control…

    That said, I am currently trying to change my workflow to use vim instead of Visual Studio Code, due to my laptop’s small screen size. Rust-analyzer works great in vim too, but I still need to tweak a few things, like how warnings from cargo check are being displayed…


  • I’m mostly using Rust for a spare time Visual Novel Engine (and Visual Novel) project.

    I picked Rust, because I wanted to do something productive with my higher-free-macro crate (which is a tech-demo, but hey, if I have written it, I can just as well use it for something). If you want to get an idea how scripting the VNs in that engine will work, check out the “text adventure” example in higher-free-macro. However, Rust is definitely not an ideal choice for this project. Since performance usually isn’t a concern for visual novels, a higher-level, pure functional language like Haskell or Lean4 would probably have been a better option.

    Apart from that I’m using it for many smaller things. For instance I’ve written a small tool for my status bar, swaystatus. (I was not aware that i3status-rust exists when I started working on it, and now I am already committed.) Here I chose Rust mainly because I wanted to learn about Foreign Function Interface in Rust. While I didn’t upload the sources to github until recently, I mostly had been working on this tool several years ago, when I still was a Rust newbie. However, I got back to this project some weeks ago, when I realized that I would like to have an ALSA volume display, which is now in a WIP state on a separte branch.

    I’m also using Rust for some out-of-tree prototypes at work. In this case the main reason for choosing Rust is development speed. I’m using Iced.rs to build those prototype GUIs, and Iced is an amazing toolkit. Making a prototype with it is shockingly fast. If I were to do something similar with basically any other GUI toolkit, it would take me significantly longer.

    And last, but not least: I’ve published a free app for SailfishOS which is compatible with passwordmaker.org: Passfish, and its underlying library, passwordmaker-rs. Here I chose Rust, because it’s way less error prone than C++ (and let’s better not talk about QML JavaScript). Also, I wanted to show that using Rust for SailfishOS app development is viable, and that it’s actually a quite pleasant experience. (If you want to try passfish, builds are available via the official SailfishOS store, or on OpenRepos).




  • “PPA” is Ubuntu’s branding for third party repositories. So, of course you will have a hard time adding a Ubuntu-specific third-party repository to anything that isn’t the Ubuntu version it’s made for…

    Debian of course supports third party repos, just like Ubuntu. On Debian they just aren’t called “PPA”.


    For more information on how to add third party repos to Debian (or Ubuntu, if you don’t use Canonical’s weird tooling), check out the Debian Wiki page on UseThirdParty or SourcesList. There’s also an (incomplete) list of third party repositories on the wiki: Unofficial. And just like with PPAs, anyone can host a Debian repo.


  • I wouldn’t call Monads a “language feature” of Rust.

    There are some types in the standard library that have Monad properties (Option, Result, Vec,…), but there is no Monad trait that would allow to be generic over them.

    There have been attempts to introduce such a trait, the most well known probably being the higher crate. However, even with that crate, it’s not easy to work with Monads.

    For instance, in the stable tool-chain, it’s currently (to my knowledge) not possible to express a Free Monad without using macros. If you care for the details, I’ve written a blog post about my Adventures with Free Monads and higher. With the Nightly toolchain it is possible to write a generic Free Monad, by the way, thanks to non-lifetime-binders.

    Other Monads, like State, Reader and Writer, are also challenging to implement in Rust. I did get them to work, however I failed to implement Applicative for them, so, while they are mathematically Monads, they do not have higher’s Monad trait. Here a possible future improvement of non-lifetime-binders could help. Again, a blog post: Writer and State Monad in Rust, based on higher.

    Oh, and last, but not least, do-notation in Rust is a bit inconvenient, because of lifetime rules and lambda captures. For instance, using non-copy types is messy. I’ve added explicit clone support to higher, but that’s a crutch, and overly verbose.




  • soulsource@discuss.tchncs.detoRust@programming.devWho's working on a "smaller Rust"?
    link
    fedilink
    English
    arrow-up
    5
    arrow-down
    3
    ·
    edit-2
    6 months ago

    Haskell.

    I’m not joking. If you want something that’s very similar to Rust, but doesn’t have the restriction of being a systems language, then Haskell might be the right thing for you. Unlike Rust, Haskell is Pure Functional though, so it forces you to have an even cleaner architecture.

    If Pure Functional isn’t your beer, then you could also check out the language that inspired Rust: ML. If I remember correctly, Rust was started as “something similar to ML, but suitable for systems programming”. So, it only feels natural to take an ML dialect if you want “something similar to Rust, but without the restriction of it being suitable for systems programming”.

    A popular ML dialect would for instance be F#, which is built on top of the .Net runtime and is therefore compatible with C# and the likes. On the other hand, in order to make it compatible with C# and the likes, there are some weird compromises in F#…

    Or, if you (like me) dislike the idea of having a Garbage Collector, you could go for Lean4. That’s what I’m learning currently, and it feels a bit like a bastard child of Haskell and ML.


  • We are in a better situation regarding the addition of new languages. Most of our devs (don’t know the exact count, 40-50 I guess) are dissatisfied with C++ in one way or another. Our company started out with Unity (which uses .Net), so most of our senior devs have experience with other languages too, and those who don’t are generally young people who haven’t had time to get stubborn yet 😜.

    Our technical director pushes towards functional programming pretty strongly, and he gave most of us the opportunity to participate in a course by FP Complete, which was a bit about Haskell, but mostly about Rust. So, most of our coders have at least seen Rust. Some liked it enough to do spare time projects in it, and as far as I can tell there is no strong dislike towards the language from anyone in our team.

    However, there is no consensus yet amongst seniors which language besides C++ we should introduce. Our tech director leans towards Rust for business reasons (-> the argument is that many devs like Rust, so finding Rust devs should be easy). Some, though they dislike C++, would rather keep it exclusively, as they doubt the benefits of other languages would outweigh the overhead (training, writing FFI bindings). Then there are those (including me) who would go directly for a pure functional language…

    And last, but not least, there is the biggest reason why we haven’t introduced any languages besides C++ yet: Time. We would need time to experiment with integrating languages into our tooling, and we simply are too busy at the moment to do that…


  • The “it’s hard” claim is also a bit of a misconception imho. Rust for sure has a high entry barrier, but it isn’t particularly difficult, at least in comparison with C++, which I’d consider its biggest competitor. While it’s easy to start working with C++, it’s a horribly complex language with hard to use features, lots of weird edge cases, and tons of missing pieces, that one has little chance of ever learning properly, because it’s just so much to keep in mind at all times… Oh, and don’t get me started on how error prone memory management is without a Borrow Checker…

    Sorry for the rant, back on topic: I agree that it’s not the right tool for many domains. That’s what I was thinking about when I wrote that people might misunderstand what niche it tries to fill. If one needs a low level language that is very explicit about performance costs, and offers memory safety and (some) abstraction at zero runtime cost, then Rust is definitely worth a look. If performance is not a key concern, then higher level languages might be a better choice, because one can build things faster, and focus more on the problem at hand instead of low-level details.

    We are at work in a similar situation, as we would like to add another programming language besides C++ to our projects, and Rust is currently the top candidate. However, one of our goals is to use abstractions that are common in functional programming, and that’s where I think Rust is a suboptimal choice. I’ve been playing around with such abstractions in Rust recently (I’ve written blog posts about Free Monads and Reader/State Monads in Rust), and my conclusion is that Rust isn’t the right tool if one wants to use those. (Or, rather, those abstractions are not suited for the domain of systems programming.)

    We are using Unreal Engine, so C++ is the obvious choice for performance critical code. Rust would then fill the same niche, and while it obviously would be much more convenient to use than C++, we would still need to train people, and set up FFI bindings. If we, however, are already willing to do that, we could also go all the way and introduce a higher level pure functional language. That way we would actually get a tool that covers a different domain and is suitable for abstractions coming from functional programming. We could then choose, based on a system’s requirements, if we need to focus on performance (-> C++), or if we can trade a bit of performance for much easier to write/maintain code (-> whatever high level functional language we pick).

    That’s why, as it stands now, I also won’t push towards the adoption of Rust at work.


  • Controversial opinion: There are only 2 kinds of people that think Rust will not become a widely used language:

    • Those who don’t bother to learn it, and only argue about it without any hands-on experience, and
    • those who don’t understand which niche Rust tries to fill.

    For me it was funny, btw. I started out as basically a Rust fanboy, back when the “First Edition of The Rust Book” was still just called “The Book”…

    Then I learned a bit of Haskell, and was immediately disappointed that Rust doesn’t offer the same convenience when it comes to working with Traits (cough Higher Kinded Types cough). So, while I never considered myself part of the first group, I definitely was part of the second for some time.

    However, the more I’ve been trying to abuse Rust for stuff that would be better done in a higher level language (like Haskell), the better I understood why Rust doesn’t offer those abstractions: They often can’t be zero-cost, and using them in a language that tries to be very explicit about performance costs becomes very verbose… In other words, I learned the hard way what “systems programming” means in the case of Rust, and which languages it competes with, and which it doesn’t.


  • I didn’t look beyond the main parts of the HTTP moduel, but what I’ve noticed basically immediately was that your pub fn start_server(address: &str, request_handler: fn(Request) -> Response) -> io::Result<()> uses a function pointer parameter.

    This is overly restrictive. fn a()->b only accepts fns, and closures that do not capture their environment (see the book’s chapter on closures). In order to accept closures that capture their environment, you could make that function generic: pub fn start_server(address: &str, request_handler: F) -> io::Result<()> where F : Fn(Request)->Response + Clone +'static.

    • The Clone requirement is necessary, because you need to pass a copy of the handler to each spawned thread.
    • The 'static lifetime is needed because you can’t guarantee that the thread doesn’t outlive the call to start_server.

    Now, this can be improved further, because Rust offers a tool to guarantee that all threads are joined before run_server returns: Scoped Threads.

    • Scoped Threads make the 'static requirement unnecessary, because the function that contains them outlives them by definition.
    • In addition, the Clone requirement is not needed either, because due to the limited lifetimes, you can take request_handler by reference, and all references are Copy (which is a subtrait of Clone).

    With scoped threads, a version of your function that could be generic over the request_handler could look something like this (I haven’t tried to compile this, it might be utterly wrong):

    pub fn start_server(address: &str, request_handler: &F) -> io::Result&<()> where F : Fn(Request) -> Response {
        let listener = TcpListener::bind(address)?;
        std::thread::scope(move |s| -> io::Result<()>{
            for stream in listener.incoming() {
                let stream = stream?; // I think ? works here too
                s.spawn(move || {
                    handle_connection(stream, &request_handler);
                });
            };
            Ok(())
        })
    }
    

    Edit: Sorry for the messed up characters. & should of course just be the ampersand character, and < should just be the less-than character.



  • Before you get overly excited, we plan to introduce it later this year. As in game-dev “plan”, as in “it might be cut or delayed” 😜. What is holding us back is that we need time to get a Rust toolchain set up for all our target platforms, which have certain requirements that the toolchain needs to meet, and time is always a tight resource in game dev.

    That said: Our technical director is very adamant at pushing us towards a more functional programming style (his website explains why). If we could, we would go pure functional right now, but it’s really hard to find people who have experience with fully functional languages, and therefore we want to have the next-best thing, which is Rust. (Or F# for Unity projects. We don’t have any Unity projects right now, but we already have used F# in Rescue HQ, for instance.)

    And finally, to answer your questions: I work at stillalive studios. Here is a list of our open positions: https://stillalive.games/careers/ Also I can say from personal experience, that the “speculative application” paragraph is definitely true.