Skip to content

Add a lazyt class for delaying computations #5090

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 9, 2019

Conversation

romainbrenguier
Copy link
Contributor

This class is meant to be used for delaying the computation of a value to the first time we need it, but avoid recomputing it if it is needed several times.
In particular I would have found such a class useful when writing this pull request: #5078

  • Each commit message has a non-empty body, explaining why the change was made.
  • Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • [na] My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • White-space or formatting changes outside the feature-related changed lines are in commits of their own.

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️
Passed Diffblue compatibility checks (cbmc commit: e5bf82d).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/126077346

@codecov-io
Copy link

codecov-io commented Sep 5, 2019

Codecov Report

Merging #5090 into develop will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #5090      +/-   ##
===========================================
+ Coverage    69.66%   69.66%   +<.01%     
===========================================
  Files         1319     1321       +2     
  Lines       109250   109269      +19     
===========================================
+ Hits         76106    76125      +19     
  Misses       33144    33144
Impacted Files Coverage Δ
src/util/lazy.h 100% <100%> (ø)
unit/util/lazy.cpp 100% <100%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 78fc2b7...8dbbca1. Read the comment docs.

src/util/lazy.h Outdated

/// Force the computation of the value. If it was already computed (even if
/// \p info was different), return the same result.
valuet force(infot info)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find "force" an unintuitive name. How about "evaluate", "compute" or "force_evaluation"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

force is used by .net, scheme and ocaml https://en.wikipedia.org/wiki/Lazy_evaluation so I think it's relatively standard, but I don't know if someone encountered similar concepts in other libraries or languages?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's a standard term then that's fine.

static lazyt from_fun(std::function<valuet(infot)> fun)
{
return lazyt{std::move(fun)};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not a public constructor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having a static function with a name is clearer in that case, when I read lazyt::from_fun(f) I know we use a function f to make a lazyt object, but lazyt(f) is more obscure.

This generalizes a pattern for which we have several potential usage.
This tests that the force function returns the expected result and the
evalution function is not called more than necessary.
@romainbrenguier
Copy link
Contributor Author

@owen-mc-diffblue @danpoe following the suggestion of @LAJW I've removed the infot for force, so that it cannot be called twice with different arguments.

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️
Passed Diffblue compatibility checks (cbmc commit: 8dbbca1).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/126233098

return s.length();
};
auto lazy_length =
lazyt<int>::from_fun([&]() { return length_with_counter("foo"); });
Copy link
Contributor

@LAJW LAJW Sep 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😊 https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/lazy-expressions
And now you could even infer return type by doing:

template<T> auto lazy(T func) -> lazyt<decltype(func())> { ... }

Also, () in zero-argument lambdas is optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm adding it in a follow-up PR: #5101

@romainbrenguier romainbrenguier merged commit 1b4de42 into diffblue:develop Sep 9, 2019
@romainbrenguier romainbrenguier deleted the feature/lazy branch September 9, 2019 06:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants