Rust over the top


#1

The Rust language is good. I would like to use it more. Everything attached to Rust is too much work.

I worked with C and other languages to build simple quick utility applications. C development is too slow when you move past the most basic code. The Rust compiler includes a lot of useful stuff for those slightly larger projects but the rest of the Rust infrastructure is too much work.

I end up using easier languages that just work without jumping through all the rusty hoops.

The cargo system probably helps with very large projects but is a speed bump when you want just a little bit of extra code. For my small beginner projects, the infrastructure becomes a roadblock and I switch to another language, removing opportunities to explore Rust.

Of three attempts to use Rust, one failed due to the lack of a working GUI and two failed because the infrastructure overheads were too difficult.

How did you learn Rust? Are there tutorials for people who just want to run up a little utility the way you would with gcc?


#2

Write a small program with gcc:

$ vim test.c
$ gcc test.c
$ ./a.out

Write a small program with rustc:

$ vim test.rs
$ rustc test.rs
$ ./test

Write a slightly bigger program with Cargo + rustc:

$ cargo new --bin testproj
$ cd testproj
$ vim src/main.rs
$ cargo run

Using cargo is only one extra line, so I don’t see why you wouldn’t just do that all the time.


#3

How do you find it to be a speed bump? My experience was quite different:

  • Adding a dependency is adding a line in Cargo.toml. Comparison with a few other language tools:
    • C++: CMake scripts + dealing with linker issues can be hours
    • Java: Maven uses XML, which is highly verbose / lots of noise when trying to see what features are on or off.
    • Ruby: Bundler’s good, and Cargo reminds me of that.
  • Running tests is built-in to the language, so I don’t have to download a testing library and link it; I can just run cargo test. That said, I do use test libraries to make tests easier to write

I admit I’ve had a number of painful GUI related problems, usually due to error messages dropping detail, though the related libraries have improved since.

By reading most of the first edition of the Rust book (the second edition didn’t exist yet), and jumped to random pages in Rust by example. I was just happy (like, really happy) that the compiler gave me colourful error messages and told me where I went wrong.


#4

One of the things I found difficult in Rust is finding code in the cargo system. I want to find one little bit of code to do x or to show an example of x. Searching the code without installing the code was difficult. Finding the minimum download of code to do something was difficult.

The simple example in the tutorials seemed to be in limited areas. I might want to do something like read Exif data from an image to get the image orientation. That is really easy, by comparison, in the language I ended up using. In the other language, there are lots of examples and the code is in small chunks so you can use only what you want.

For the file read portion of that project, I searched for Rust equivalents and went round in circles. I might try again after I finish the application in the other language. I can use the other language to easily display files and data to work out their formats. That will reduce the work required to understand what is happening in Rust.

I am also waiting on a really easy stable GUI. In some other languages, the GUI is easy, stable, and lets me quickly display the data before conversion, during conversion, then after conversion. My attempts with Rust to display activity in progress ended up crashing into GUI library problems. I will look at that gain when there are new versions of the GUI libraries I tested last time.

I might give up on the GUI approach for development and settle for things like sitkevij/hex
to display stuff in the command line.


#5

Looking at your post, I have the impression that you mostly hit library maturity issues, rather than core language or tooling issues. Would you say that this accurately represents your point?

It is certainly true that the Rust library ecosystem is still young in many areas, GUI being a common pain point. Documentation is also a common issue with young programming languages. It is pretty clear that at this current stage of Rust’s growth, older and more established programming languages have a clear advantage on these fronts.

The hard part here is that the missing libraries/docs will not get written until someone decides to take the decision of fighting this ecosystem immaturity, while as you point out the easy path is often to just use an older ecosystem. These kind of chicken-and-egg problems can take a very long time to resolve, I am not sure what we in the Rust community could do to help them get resolved faster.


#6

True. The result is I did not finish anything useful. If I had a useful running program, I could contribute back some of what I find missing from the documentation. I am not going to contribute when I cannot prove the code works and is useful. I have a 12 week project starting for something else then will experiment again.


#7

I’ve got a personal project with >9MB of CMake files in it, due to all sorts of stupid quirks that I can’t easily resolve. I’m rewriting it in Rust in my spare time and thus far the largest and most irritating part of the project is disappearing rapidly due to either pure Rust ports of the code, or not having to wrangle a bunch of obscure build systems into cargo’s reach.

Once you get your head around cargo, it’s great. It’s really not all that complicated, and the 2018 edition changes will probably help you a lot.

For what it’s worth, the easiest way would be to write a shared/dynamic library using Rust and load it via C (wrap it via C++ if needs be on your end) so you get your Rust code included. You can then write the test code in Rust and hit it up with cargo’s test and benchmarking (and fuzzing via extensions), ensuring it works as you expect.

My personal approach is writing a server in Rust and having the GUI connect to it (but having the GUI launch it as a child process). This way I can leave the nasty GUI code to whatever suits the platform, and have the Rust code be as generic as possible. (I also extend it and fire the data across networks allowing for true client/server mode.)

I’m not a huge fan of the Rust GUI libraries, but I’m also not the biggest fan of GUI programming :slight_smile:


#8

What do you use for your GUI parent?

I currently have a project in PHP that was going to be in Rust then becamse too difficult. The easiest way to describe it is a process that sorts through tens of thousands of files, a terabyte of data, producing lists of files of interest with summaries. The front end looks a bit like a file browser for the selected files and expands out the summary information when you select a file. The display can also show cross references. There is a tiny bit of Javascript to get the expanded content into the HTML.

What I really need is to have the scan run in the background and update the display at short intervals, say every 5 seconds. Some options in the display need to change data in files then rerun the scan for those files.

The whole application should be a single executable, not a Web site installation.

As an intermediate step, I would look at a Rust program, or programs, I can run from PHP via exec and get a result.


#9

Mostly HTTP/Web. But anything is possible. I lean towards sockets for access.

If it needs to be done, and done soon, use Go, use the inbuilt webserver integration, and self-host the “site”/UI inside it. Or use Electron and Neon. My bias is towards Go. Rust can do it too, with the caveat that it’s not bootstrapped by stdlib like Go is (at last not the protocol level) . You might want to look at things like hyper if you don’t want to have to build up from TCP sockets.

I’ve written a few dozen Go applications that do things like what you’re describing, but Rust destroys them for performance (even with all of the garbage collection updates).

If the data is as large as it sounds, and it’s not single-user, build a database. Use something like CouchDB and litter the drive with views (I use NoSQL for document storage; you can still have common values, but the idea is to let the model change without breaking backwards compatibility or forcing crazy update costs; I also use CouchDB so I can do real-time sync/backups). Query the views, merge them, and then filter them. If it is single user, I’d be guided by what makes sense. If the data set is due to grow to something beyond what is easy to adapt around you’re already looking at needing a database of sorts. There’s no reason you couldn’t use a locally hosted one, or an embedded database, but it comes down to needs.


Edit:

To be clear, Go is better for when there’s a deadline and you need to make sure it’ll work rapidly within the constraints of given platforms. If you have the time Rust is far nicer in the long run (though you lose out on Go routines); once we get stable coroutines I’ll likely be much happier with Rust. It’s just that Go was really designed with what you’re describing in mind.

An example of a desktop application with Rust involved is Finda, which I stumbled across trying to find the neon-bindings site: https://keminglabs.com/blog/building-a-fast-electron-app-with-rust/ Essentially it marries Electron with Rust via Neon (Neon is used to build Node.js modules), which is the “default” for many people I know now (albeit NodeJS with C/C++ modules). I personally don’t love shipping a web browser’s worth of content each time I push an application, which is why I lean on Go when I need to do something quickly.

Rust’s web frameworks should guide you down a similar path to how Go works. It’s really down to whether you have the time to go down the rabbit hole of learning parts of Rust. By the sounds of it you’re looking at using it with limited experience, which is great (for learning), but also problematic (because there’s a lot that won’t do what you want). I’d personally put more time into learning bits of Rust and its web frameworks, messing with merging a server and client in the same binary (mpsc can be use if you’re not intending to have external clients), and then hosting the data via the “client” side (web interface/TCP listener/framework listener).


#10

Thank you for the explanation. Go sounds nice and I tried it once before. There are things about Rust development I prefer over the Go development. I will start with some simpler programs to learn Rust.

An intermediate db is of interest. I tested SQLite3 in another program. In both cases the summary data is small compared to the source data, making SQLite an option.

I also experimented with flat files in one case. The data can be structured so that new items are appended in the background and files rechecked by the front end at a page change or other action.

The only real time changes are ones when the user submits a change. That would have to tell the backend to rescan a directory.


#11

Trust me, you’re far from alone on that :wink: I personally alternate based on deadline and requirements. Rust has some really nice parts, but Go’s “it’s already done” standard packages is just amazing at times.

There’s a big range of things that the two languages cover, and since I typically interoperate via sockets (at least externally), it’s how I solve the problems. I actually dropped Python as a primary prototyping language in favour of Go a while ago; I write small (hacky/quick) utilities in Rust now (I went from Python to Lua to Go to Rust in that case).

IMO if you want to learn Rust well, build smaller things in it that speed up your work. Build them as a library + binary in the same crate, so you can merge the library into your binary or build a larger tool (eventually upgrading it).

I know, much of this is basic language learning advice/commentary, but I also struggled with the transition to Rust because I was so used to just knowing what I was doing in the other languages. (In my case Go is probably to blame for that because it is very intuitive, but it has massive gaps that make it so–like a total lack of generics in userland.)

I’d lean towards NoSQL options or triple stores, since most things like this tend to evolve a lot over the course of their lives. It’s really personal preference, and then what you can make perform.

Just remember that if you’re building a database, prototype with an existing one (embedded or external). If you need multiple users or crash resistance use an external database. Only build a new one if you can’t find a better option out there (I know people who use redis to prototype for this reason, and stick with it in development due to its capabilities). Re-inventing the wheel has its place, but you’re asking for additional development overhead each time you resort to doing it. (Now if only I could make myself realise that…)

I’d say look into CouchDB then, as it’s going to make your life a lot less complicated. It is by far not the only option, it’s just really easy to get working, and has all of the things you’re talking about as features. (Update database -> update view, but poll enabling stale views to prevent stalls.)

This could also be my Erlang bias, but I also tend to recommend RabbitMQ to people who need massive/complex queues with concurrency support. Don’t get me wrong, I’m sure at some point I’ll be recommending more and more Rust applications/approaches, it’s just that there’s a reason certain things are established, and until you actually try them out, or understand their patterns, you can’t really find a better way to approach it.