I understand that when a function owns data you can't return references to it, because once exited the owned data is freed.
But what about when, to reduce typing, you just want a convenient function/macro to produced an owned value of some kind (that isn't needed for anything else) and produce a reference? Is there no way to accomplish this reduction in code without adding the expense of clone?
Here is a specific example that illustrates the desired outcome well, but I feel like this is a general Rust programming issue. In polars, I want a convenience function to get column names:
pub fn columns(lf: &mut LazyFrame) -> Result<Vec<PlSmallStr>, PolarsError> {
let schema = lf.collect_schema()?;
Ok(schema.iter_names().cloned().collect::<Vec<PlSmallStr>>())
}
The function of course works, but because schema
is owned I must clone
. Maybe not a big deal - I don't have millions of columns. But again, this is a general developer efficiency issue; I just want some kind of way to tell the compiler to write these lines of code for me.
For instance, if I don't use this function by instead copying/pasting everywhere, it's easy to scope schema
such that it lives long enough. So I thought, maybe I write a macro so that schema
appears in scope:
macro_rules! columns {
($lf:ident, $names:ident) => {{
let schema = $lf.collect_schema()?;
$names.extend(schema.iter_names());
}};
}
pub(crate) use columns;
But because I need let
that means my macro must also scope it within a code block (same problem).
Is there no way to write a purely code-reducing convenience callable to get the schema and return the names so that I don't have to copy/paste these two lines everywhere?:
fn caller(lf: &mut LazyFrame) {
// 1
let schema = lf.collect_schema().unwrap();
// 2: notice no clone since schema lives long enough to "do stuff" below
let names = schema.iter_names().collect::<Vec<PlSmallStr>>()
// would much rather just call columns(lf)... but not at the expense of cloning
if names.contains("stuff".into()) {
// do stuff...
}
}
I would love a way to inline or macro those 2 lines as-is. Does nothing exist to serve this minimal code aesthetic?