• 0 Posts
  • 25 Comments
Joined 2 years ago
cake
Cake day: June 15th, 2023

help-circle

    • cargo install is for installing rust programs for your user, not for adding dependencies to your Rust project. Many cargo subcommands can be installed this way, for instance cargo bloat.
    • The file you are talking about is called Cargo.toml, because it is the file you need to write in order to configure cargo for your Rust project. TOML is the name of the file format. For details, please see the introductory chapter to Cargo in the Rust book.
    • Cargo recently got a new subcommand called cargo add, which allows to add dependencies directly on the command line. However, all it does is to add/edit/remove the respective lines in Cargo.toml. (Personal opinion: I have found it way easier to just edit the file directly than to learn yet another command…)

    That said: You still need to edit the Cargo.toml file, even if you solely use cargo add to manage your dependencies. That’s because that file contains a lot more information about your project than just the dependencies. For instance the current version, the feature-flags, your name, a link to the public repo,…


  • I haven’t done much Rust coding this year yet, mainly because I am trying to learn Lean4 and spent the last couple of months writing a (partially) formally validated (but not very fast) Binary Heap in Lean4.

    However, a few days ago I had an inspiration at night, that brought me back to my Rust spare time project: The visual novel engine I had started last year.

    For now I only did a relatively small change, but it’s one that will save me a lot of time (and nerves) later on. I am using a Free Monad based embedded Domain Specific Language for writing the game logic. The change now was to wrap that Free Monad in a State Monad Transformer, which I use to store the game state in.

    This idea seems to be working surprisingly well, and that has given me enough motivation to return to this project and to keep developing it further for now.


    Long and boring explanation with way too much detail:

    Sorry for going on a tangent, but there is a Rust-specific detail that makes this cool beyond the usual advantages of using a State Monad Transformer, and I cannot stop myself from sharing.

    For composing a large Free Monad, do-notation is more or less a must-have. However, do-notation in Rust only works well with types that implement Copy. If you want to use any other type in do-notation, you can only access variables of it in the following two lines. An attempt to access the data later will lead to an ownership problem (explained here). I have tried to overcome this by adding additional syntax to do-notation, but that is a crutch at best.

    So, this is where the State Monad Transformer comes in. It side-steps this problem by moving the state out of the do-notation block into the Free Monad’s Pure-nodes. That way it is readily available via the State Monad Transformer’s get()/put() functions, and the “use within two lines” limitation is not a big issue any more, as one can always get the value on one line, do something with it in the next line, and write the result back on the second line.




  • Behind all the negative tone there is a valid concern though.

    If you don’t know Rust, and you want to change internal interfaces on the C side, then you have a problem. If you only change the C code, the Rust code will no longer build.

    This now brings an interesting challenge to maintainers: How should they handle such merge requests? Should they accept breakage of the Rust code? If yes, who is then responsible for fixing it?

    I personally would just decline such merge requests, but I can see how this might be perceived as a barrier - quite a big barrier if you add the learning cliff of Rust.









  • 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).



  • 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.




  • 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.