How to name the `result` variable?

Hi! This is a stylistic question, which is not really Rust specific. If you are writing a function, and it builds its result piece by piece, how do you name the variable which holds the result? I've personally have used the result name (stolen from Fowler's Refactoring), but now I am somewhat unsatisfied with it, and looking for better suggestions :slight_smile:

Here's a poll with some popular conventions I've seen before

  • result
  • res
  • ret
  • acc
  • unique name per function: foo for fn make_foo()

0 voters

1 Like

If you mean something the returns from a function then I at least name it depending on what the function returns. like texture = get_texture() If I have more textures I name them more specifically depending on what I expect the function to return.

2 Likes

Let me clarify a bit! I am talking about the name of the variable withing a function, ??? in the following made up example:

fn get_texture(name: String) -> Result<Texture, Error> {
    let ??? = load_from_file(name)?;
    if ???.size() > spare_capacity {
        return Err("Not enough capacity")
    }
    for i in 0..mip_levels {
        ???.construct_mip_level(i);
    }
    Ok(???)
}

A lot of the time when I'm doing a complicated chain of map() and and_then() followed by an if let Err(e) = ... I'll break it into two steps and store the result in a temporary result variable.

let result = MDBook::load(&book_dir)
  .and_then(move |mut b| {
    b.config.set("output.html.livereload-url", &livereload_url)?;
    Ok(b)
  })
  .and_then(|b| b.build());

if let Err(e) = result {
  error!("Unable to load the book");
  error!("Error: {}", e);
  for cause in e.iter().skip(1) {
    error!("\tCaused By: {}", cause);
  }
}

I've found that pattern seems to be more readable than merging them all into one big if let Err(e) = x.and_then().and_then().map() { ... } statement.

I used to use out, but in is a reserved keyword in Rust, so this bites as soon as I want the other for symmetry.

1 Like

If that ever happens, I use the "unique name per function" way of doing this. But mostly, I try to avoid this:

If I need to build Result<_, _> objects, I either have a function which itself returns a Result<> type or I have defaults I can use or I ::std::process:exit(1) on Err(_) (normally only if I'm in main()). Therefor, I never have a variable which holds a Result<> object because I use function chaining, the ? operator and Result<>::* functions to avoid it.

Example from one of my projects:

let contact_data = rt
    .store()
    .get_by_hash(hash.clone())
    .map_err_trace_exit(1)
    .unwrap()
    .ok_or(CE::from(format!("No entry for hash {}", hash)))
    .map_err_trace_exit(1)
    .unwrap()
    .get_contact_data()
    .map_err_trace_exit(1)
    .unwrap()
    .into_inner();

map_err_trace_exit() is a helper which calls a trace_error() function if the Result<> contains an Err() and exits afterwards. Because of types I need to unwrap() after that (which is safe, as there will never be a Err(_) after a map_err_trace_exit() - I even created a map_err_trace_exit_unwrap() though I did not manage to convert this piece of code just yet.

Meh, I still use out anyways. Function inputs usually benefit from unique names even when outputs don't.

I would still call it texture in this case or perhaps in this context image_data So what I'm trying to say I often name things depending on the context.

I used to use unique names per function but now I use res whenever I need to build a result value. Unique names get confusing real quick when you have multiple temporary values, accumulators, etc.

With res the intent is clear.

If it's unavoidable to have such a variable at all, I go with result. The exact meaning can easily be inferred by the surrounding method's name. It's more robust against refactoring (less redundancy) and it's purpose (being emitted at the end of the function) is clearer to me than texture, which might be an input or intermediate variable as well. result_texture might be an option if result+<method name> doesn't provide enough context.

I don't like abbreviations like res. This could be resource in many cases as well.

I like to use out for byte/char/etc.-streams and writable file handles. In some popular languages out is used as a modifier.

3 Likes

I use accumulator when I am returning a sum or a product. Otherwise I'm in the result camp.