Is postfix match a thing?

Since I read about the idea in one of the away syntax threads, I’ve spotted quite a few places this would make my code more readable. It’s like a ? but more general. I’d be very supportive of any moves to develop this idea! An example of what I’m talking about (decoding images in rocket)

    let mut encoded_picture_buf: Vec<u8> = Vec::new();
    image::load_from_memory_with_format(&picture_data, picture_type.into())
    .match {
        Ok(i) => i,
        Err(e) => return Either::Left(ErrorResponder::static_msg("cannot decode supplied image")),
    }
    .resize_exact(PICTURE_WIDTH, PICTURE_HEIGHT, image::FilterType::Lanczos3)
    .write_to(&mut encoded_picture_buf, image::ImageOutputFormat::JPEG(80))
    .match {
        Ok(()) => (),
        Err(_) => return Either::Left(ErrorResponder::static_msg("could not encode image to jpeg"))
    };

The fascination with chaining reminds me of people writing point-free code in Haskell.

In your specific case, I’d use ? instead even if postifx match was available. Why is that code more readable than the plain

let mut encoded_picture_buf: Vec<u8> = Vec::new();

image::load_from_memory_with_format(&picture_data, picture_type.into())?
    .resize_exact(PICTURE_WIDTH, PICTURE_HEIGHT, image::FilterType::Lanczos3)
    .write_to(&mut encoded_picture_buf, image::ImageOutputFormat::JPEG(80))?;

?

And consider what you need to do when trying to extend the code. Say you don’t want to resize small images:

let mut encoded_picture_buf: Vec<u8> = Vec::new();

let input_image = image::load_from_memory_with_format(&picture_data, picture_type.into())?;

let small_image = if image.width() > PICTURE_WIDTH && image.height() > PICTURE_HEIGHT {
    image.resize_exact(PICTURE_WIDTH, PICTURE_HEIGHT, image::FilterType::Lanczos3)
} else {
    image
};

small_image.write_to(&mut encoded_picture_buf, image::ImageOutputFormat::JPEG(80))?;

This is indeed longer, but more readable and extensible in my opinion.

That’s mostly because your application logic depends on what the web server expects to get. If you switch to another web framework you’ll probably have to replace Either and ErrorResponder with something else.

5 Likes

I can’t use Try here because i’m not returning a Result. Even if Try were stable, and also I created my own sum type and implemented Try on it, I still can basically only do early return. match is immensely more powerful.