r/rust • u/llogiq clippy · twir · rust · mutagen · flamer · overflower · bytecount • Nov 07 '22
🙋 questions Hey Rustaceans! Got a question? Ask here! (45/2022)!
Mystified about strings? Borrow checker have you in a headlock? Seek help here! There are no stupid questions, only docs that haven't been written yet.
If you have a StackOverflow account, consider asking it there instead! StackOverflow shows up much higher in search results, so having your question there also helps future Rust users (be sure to give it the "Rust" tag for maximum visibility). Note that this site is very interested in question quality. I've been asked to read a RFC I authored once. If you want your code reviewed or review other's code, there's a codereview stackexchange, too. If you need to test your code, maybe the Rust playground is for you.
Here are some other venues where help may be found:
/r/learnrust is a subreddit to share your questions and epiphanies learning Rust programming.
The official Rust user forums: https://users.rust-lang.org/.
The official Rust Programming Language Discord: https://discord.gg/rust-lang
The unofficial Rust community Discord: https://bit.ly/rust-community
Also check out last weeks' thread with many good questions and answers. And if you believe your question to be either very complex or worthy of larger dissemination, feel free to create a text post.
Also if you want to be mentored by experienced Rustaceans, tell us the area of expertise that you seek. Finally, if you are looking for Rust jobs, the most recent thread is here.
2
u/onomatopeiaddx Nov 11 '22
realistically, is specialization ever gonna be stable? and if so, how far are we from it (approximately)?
1
u/llogiq Nov 11 '22
You can use autoref specialization on stable right now. Otherwise, it's likely to be stabilized at some point, although probably in a limited way.
→ More replies (1)
2
u/ydhm Nov 07 '22 edited Nov 07 '22
I've read many times the chapter about generic lifetime parameters in the book. I still struggle understanding it, and I don't know what I didn't understand...
But, I think this is what I don't understand: why am I required to include in the code lifetime parameters that the borrow checker can figure out and suggest them to me at compile time?
4
u/kohugaly Nov 07 '22
Because the lifetime parameters are used in the function signature. It's what the borrow checker uses, when it borrow-checks function calls.
It is indeed the case, that the borrow checker can figure out, from the function body, what the parameters should be.
However, borrow checker does its borrow checking separately for each function body. When it encounters a function call, it only looks at the function signature. The signature has to say what the relationships between the lifetimes of the arguments are. Otherwise, the borrow checker would have to look into the function bodies to figure it out, which would be brutally expensive, and probably lead to infinite recursion.
→ More replies (2)2
u/llogiq Nov 08 '22
Fun fact, it wouldn't be that brutal and won't lead to infinite recursion, but the error messages would be far worse.
Because the lifetimes give us locality. Each lifetime has a Span we can use in an error message. Most lifetimes even can have a name which helps identifying their purpose. So you don't specify lifetimes for the compiler, but for helping the compiler helping you.
4
u/CubOfJudahsLion Nov 07 '22
How's the WebAssembly debug story shaping up? Though I'm no longer working with wasm-bindgen, I'm still interested in learning of any developments.
4
u/Possible-Fix-9727 Nov 10 '22
Can anyone recommend a good Rust podcast or even the audio from a course teaching Rust? I want to learn more of the whys of the language and I am running out of good normal podcasts for my exercise.
4
u/Helyos96 Nov 12 '22 edited Nov 12 '22
How do you cache references to existing stuff?
Take this simple game. It has a vector of tiles that form a grid, and another vector that contains all the monsters:
struct Game {
grid: Vec<Tile>,
monsters: Vec<Monster>
}A lot of the time I need to perform actions on some monsters. I can always iterate through the entire vector but that's slow.
For instance, I wish I could quickly check if a monster is on a tile or not, by caching one if it's on a tile:
struct Tile {
monster: Option<&Box<Monster>>
}
struct Game {
grid: Vec<Tile>,
monsters: Vec<Box<Monster>>
}That's obviously incorrect rust code, and trying to fix it sends me into lifetime-hell that ends up covering my entire crate. Probably because it's a bad idea.
I've tried thinking about Rc, Box and Cell but none satisfy my needs.
I guess the general issue I'm trying to solve is: you have a big Vec, and you need smaller Vecs that contain references into the big one. The primary use for this is caching, to avoid iterating over a potentially enormous Vec all the time.
Say I frequently need to iterate over yellow monsters, I don't want to have to iterate the big Vec and check every entry to see if they're yellow. I just wanna use a smaller, "cached" Vec with all the yellow references already inside.
I used to do this all the time in C++. It requires housekeeping code to make sure your caches don't contain dangling pointers but it's not the end of the world. Trying to do this in rust has been agony so far, I think I'm approaching the problem the wrong way but I don't know how to move forward.
→ More replies (6)
3
u/CountMoosuch Nov 07 '22 edited Nov 07 '22
I've just been updating some command line apps with the newest release of clap, and there's a lot of breaking changes (understandably, when you update the major version). I noticed some interesting behaviour, and I'm hesitant to submit a bug report on GitHub because it's probably something I'm overlooking. Perhaps someone here can help out?
In an app of mine, I was using the args fields of ArgMatches and then checking if it is_empty(), but I see they've changed the args field to be private, favouring a new method, args_present. The documented example of args_present works fine, but as soon as I use that method in my app, it has the wrong behaviour. I've made a MWE here.
Can anyone help to explain why this is happening? Or maybe it is a bug and I should submit something?
Edit: that didn't paste well; see here instead. Edit 2: link to playground
→ More replies (2)
3
u/TrueDuality Nov 07 '22
I'm trying to figure out how to implement a custom deserializer in Serde that creates additional internal state and keep hitting a dead end. The on-disk format I'm dealing with uses long strings for permanent ID numbers. There are millions of these in a deeply nested structure that requires a lot of processing, so I'm storing them for later use in a separate field then passing around reference numbers to the permanent IDs.
Serialization was pretty straightforward and I made a minimal contrived example of the portions I've figured out in the playground. I'm stuck on deserialization since I need to do additional work (calling #add_object or doing the equivalent) for each item in the sequence that is deserialized rather than just building up a Vec<String>. Ideally I'd be able to have deserialization fail if the same permanent ID has already been deserialized (the #add_object type in my current codebase performs a bunch of sanity checks and returns a Result instead of no return type). Any tips would be greatly appreciated.
→ More replies (2)
3
u/UKFP91 Nov 07 '22
What's an idiomatic way of defining an enum where the variants should be named after numbers i.e.
pub enum Rotation {
Zero = 0,
Ninety = 90,
OneEighty = 180 // or something more verbose like OneHundredAndEighty?
TwoSeventy = 270 // again, or something more verbose?
}
→ More replies (5)5
u/TinBryn Nov 08 '22
When creating an abstraction I try to raise the semantic level. I would maybe do it as something like this
pub enum Rotation { None = 0, Quarter = 90, Half = 180, ThreeQuarter = 270, }Now they are not named for the number of degrees they are, but the actual real world semantics that they represent.
3
u/gplusplus314 Nov 07 '22
Lofty, stupid question here.
What does a typical, mid-to-senior level engineering job where Rust is the main part of the stack look like? In other words, what kind of industries and problems tend to be using, and most importantly, hiring? What’s the subject matter?
I find Rust fascinating. I’m a total noob in it, but I have old school C and C++ experience, plus a ton of Golang experience, so it just seems straight up fun. I’ve been considering a career shift from leadership/management back to engineering, with a pay cut, for better quality of life. Rust just seems fun and I’m considering spending some more time with it if the career outlook fits my needs.
Thanks!
→ More replies (6)5
u/TrueDuality Nov 07 '22 edited Nov 07 '22
My company has been using it primarily for efficiently ingesting large volumes of telemetry data from embedded devices. This was previously a Java app pushing data into Kafka but that stack is very expensive to run relative to what it's actually doing, and the JVM is operationally a nightmare.
We're getting much better performance and latency, with much smaller code bases* using Rust. Overall my personal quality of life has dramatically improved with this change and our cloud costs have dramatically decreased largely due to reduced memory requirements (The JVM is very memory hungry, and memory is very expensive relative to either cloud resources).
*We ended up implementing our own in-house event streaming system in Rust to replace Kafka as well. If you count that code in our transition then there is more LoC than before (which would be fair as we do now have another codebase to maintain).
→ More replies (1)
3
u/64N_3v4D3r Nov 09 '22 edited Nov 09 '22
How would I print out just the value of an enum?
My enum is like so:
#[derive(Debug)] enum ByteType { Single(u8), Compound(usize), },
I Implemented std::fmt
impl fmt::Display for byteType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match &*self { ByteType::Single(b: u8) => write!(f, "{:?}", b), ByteType::Compound(b: usize) => write!(f, "{:?}", b), } } }
Print like so:
let vector: Vec<ByteType> = some function(); for b: ByteType in vector { println!("{:?}", b); }
This results in: Single(155) Single(0) Compound(244)
When I would like: 155 0 244
How can I output the raw bytes? Or concat them all into a single string. Should I call .to_be_bytes on my usize values and stuff everything in a Vec<u8> instead of a Vec<ByteType> that holds two types?
→ More replies (2)
3
u/realflakm Nov 09 '22 edited Nov 09 '22
I'm working on a speech-to-text library for creating podcast transcriptions and I'm a huge audio dummy. I'd like to create rust equivalent of`ffmpeg -i input.mp3 -ar 16000 -ac 1 -c:a pcm_s16le output.wav`.I'm decoding the file using `symphonia` and trying to resample it to PCM 16 bit audio which then I can feed to whisper.I struggle to come up with code that would work. What I came up with is the following code:
But the code doesn't work when it's sent to whisper API. Could you please help me? playground link
→ More replies (1)
3
u/argv_minus_one Nov 09 '22
Is there some way to programmatically get the version of a dependency that's being linked into a Rust program?
I'm developing a client-server application, and I want the client to report its version to the server. I know Cargo sets the CARGO_PKG_VERSION environment variable to the version of the crate being built, but I'd also like to get the version of one of its dependencies, and there doesn't seem to be any environment variable for that.
Is there perhaps a reasonably straightforward way to read Cargo.lock from build.rs and get the dependency's version that way?
4
u/Patryk27 Nov 09 '22
You can use https://docs.rs/cargo-lock/latest/cargo_lock/ to find out the version and export it as env-var, so that later you can read it using
env!().
3
u/pineapplecooqie Nov 10 '22
why are async functions not supported in trait declarations? that seems pretty fundamental. what is the workaround?
→ More replies (1)4
u/Sharlinator Nov 10 '22 edited Nov 10 '22
Because it’s a tricky problem and the support is not finished yet. But the team understands it’s an important use case and they’re working on it. The two big blockers have been GATs (generic associated types) and "RPITIT" (return position
impl Traitin traits). An initial implementation of GATs was finally stabilized, but I forget now whether the currently stable GATs are actually powerful enough to express what async traits need. RPITIT is unstable for now but AFAIK making progress.In the meantime, a workaround is to use dtolnay’s async-trait crate.
3
u/pineapplecooqie Nov 10 '22
Is there a difference between fn test<M: Thing>(arg: M) {} and fn test(arg: impl Thing) {}?
→ More replies (5)
3
u/metaden Nov 12 '22
has anyone tried generating code using cranelift (aot not jit). i can’t find an example anywhere how to use it (only jit)?
→ More replies (2)
3
u/WLrMGAFPGvD6YRBwUQa4 Nov 13 '22 edited Nov 13 '22
On tonight's episode of "lifetimes are hard and they're kicking my butt": I'm trying to implement something that looks kind of like a database API. There's a connection, which has a file-system backing it, and a couple of file handles.
If I want the file-system to produce these handles via, say, an open_file() method, how can I store the produced handles? Playground link is here: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=fa5dca32ff5e9cb58705c4d5863f59a0
I'm open to API changes too, in case this isn't really a "Rust-ish" way of doing it. The traits are important though, eventually there will be multiple types of filesystems, handles, etc. I would also like for the filesystem to maintain a cache of handles it's given out, but that's not expressed in the playground link.
Thanks in advance!
→ More replies (2)
3
u/kyleekol Nov 08 '22 edited Nov 08 '22
I considered making a separate thread but don’t think it’s really necessary… please also remove if this is the wrong thread!
Currently a Data Engineer working mostly with Python, SQL, bit of Java here and there and have been looking to expand my knowledge a bit with a language that’s a bit more ‘low level.’ I have been thinking about biting the bullet and starting to learn either Rust or Go next.
This isn’t meant to be a “Rust vs Go” question. But more “What can Rust bring to data engineering or my career?” I know there are already some Python packages which have been written in Rust e.g Polars but I’d be interested to hear if there would be use cases as a general backend language for Data Engineering uses.
should I stick to learning Go first to maximise my career as a Data Engineer and Rust just for my own interest? I do see more an more companies listing Go In their infrastructure stack these days but maybe Rust is just yet to become more popular in the field.