Package development workflow

Hi :wave:

For package development in Haskell or Julia, I really like the workflow of starting with a simple version of the package I want to implement, and then exploring it in the REPL. GHCi and the Juila REPL are both great in terms of auto-reload, tab completion, and generally exploring code functionality.

In Rust, I've tried evcxr for this, and so far it's just not as smooth as the others. I don't know how much of this is because I'm not using it right, or because it's still pretty young, or because (maybe?) Rust just doesn't lend itself to this approach.

I'd appreciate any advice on

  1. If there's a better way to setup or use evcxr for this, or
  2. If there are better REPLs out there for this, or
  3. If there's a better development workflow that can give a similar advantage in terms of, I don't know, let's call it "immersiveness"

Thanks,
Chad

2 Likes

Personally, I prefer writing tests — create a #[test] function and write whatever code you want in it. With VS Code and rust-analyzer, you can use the “Rerun Last Task” command to save and run the code in one keystroke. You may be rerunning the code from the beginning, but that isn't worse in most exploratory cases, and it means that you can make an edit anywhere and see all of the consequences of it, rather than having stale results hanging around.

(And then once you're satisfied with the results, you could add an assertion and keep around the code as an actual test, if that makes sense.)

For large projects, I suggest placing the experimental test code in the “integration test” directory tests/ so that the test is compiled separately from the library itself, so recompiling the test doesn't include recompiling the library code. (But this is probably unnecessary for a small, quickly compiling library.)

2 Likes

Thanks @kpreid. I like the idea of using tests like this. It seems trickier to get intermediate results printed, since stdout is redirected by default, so there are some tradeoffs there. I also hadn't thought about tests/ allowing separate compilation, that's a great point.

After I posted the OP here I was also chatting with @miguelraz . From that discussion the cargo run --example foobar idiom also seems very useful.

I think I'll still miss REPLing for at least a while, but between this and tools like Rust analyzer, bacon, and clippy, maybe the feel can get pretty close.

Thanks again :slight_smile:

1 Like

To add to kpreid's point above, check out the incredibly useful debug_assert! macro which will run in debug mode but be optimized away in release mode.

But yes, if anyone has a REPL-y style workflow in Rust, I'm all ears, as I've gone into quite detail of the UX in Julia Land

1 Like

Even more useful for ad hoc exploration is the dbg! macro. It prints its arg list as nicely as any repl I've used. (Of course, a repl does it without a build step.)

Not mentioned yet are the IDEs (including any editor with LSP support) that let you look at the type of a variable you hover on, drill down into source code for the selected symbol, etc. This is only static exploration, not runtime exploration, but it has gotten very good.

2 Likes

Passing --show-output or --nocapture to the test harness (cargo test -- --show-output) will let the output be seen even if the test passes, and rust-analyzer passes --nocapture by default for all test runs (though I think it really shouldn't).

(Also, the redirection is actually not stdout, but a Rust std-specific mechanism that applies only to println!, eprintln!, dbg!, etc. — so you can actually bypass it by writing to std::io::stdout or stderr directly. But that's not particularly friendly to exploratory programming.)

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.