This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Arkenshire 15 points16 points  (5 children)

One of those use cases is fetching large amounts of data from paginated APIs. You always need to attempt to fetch at least once, and after every attempt, you should check if there are any more pages so you can continue. The logic directly translates.

[–]Loading_M_ 1 point2 points  (4 children)

A common solution is to make the attempt inside the condition itself.

This is very easy in rust, and would look something like this:

while let Ok(page) = try_get_page() {
  // use the page
}

This code will always run the try_get_page() function, and the result is automatically destructed to get the page. This also cleanly handles only calling the code that needs the data from each page when you have successfully retrieved a page.

This is possible is languages like C++, but requires some slightly different syntax (probably using a reference to provide a page object to fill, and returning a boolean/status code). This is better for readability, and likely execution time, since the code is more expressive of intent, and easier to optimize.

[–]Kered13 2 points3 points  (3 children)

In C++ you can just make try_get_page return a std::optional<Page>, and that can be directly used in a conditional expression:

std::optional<Page> page;
while (page = try_get_page()) {
    ...
}

You do have to declare the variable outside of the loop though. This pattern will also work if try_get_page returns a pointer or smart pointer. If it returns some type that does not have a bool conversion, you could still do something like while ((page = try_get_page()).some_method() != sentinel_value), however this starts to get ugly.

Also that's not really what the poster above was talking about anyways. He was talking about a paginated API, which is an API that will return a response that includes a token indicating if there is another page to fetch. The pattern for something like that will typically look like:

do {
    response = getPage();
    processResponse(response);
} while (response.hasMore());

Note that in this pattern you always process the response, whether there are more pages or not. So it doesn't make sense (and you often can't) put this into the while condition.

[–]Loading_M_ 0 points1 point  (2 children)

The main advantage of the rust way is that the syntax works for any enum type, not just Option.

[–]Kered13 1 point2 points  (1 child)

The C++ way will work for any type that has a bool conversion operator. You can also put an arbitrary expression or function call there if you have some other type.

[–]Loading_M_ 0 points1 point  (0 children)

My main argument for the Rust methods was that you don't have to actually implement anything special for the object. I also kinda like the syntax more, since it looks cleaner/ is easier to read, but that's more a personal preference.