From late-bound arguments to deferred computation, part 2
From late-bound arguments to deferred computation, part 2
Posted Aug 29, 2022 17:55 UTC (Mon) by NYKevin (subscriber, #129325)In reply to: From late-bound arguments to deferred computation, part 2 by tialaramex
Parent article: From late-bound arguments to deferred computation, part 2
You say "constructor," I say "function that happens to initialize some memory as a side effect." Either way, it's an implicit function call.
> It does this when the function is called, even if the function implementation actually checks the team names and discards any matches not involving Liverpool without using their FinalScore.
That's not really what I'm getting at. Your function could take SoccarMatch instead of FinalScore, and then call a private helper function which takes FinalScore if and when it actually wants to evaluate it. You *choose* to put FinalScore at the API boundary, which may make sense for your particular application, but C++ doesn't force you to do it that way. You could even do it both ways using templating... which is exactly what Rust's From<T> facilitates (i.e. you could accept a From<T> as an argument, then pass it as a T to some other function, and never worry about the conversion at all).
> Rust does have some silent conversions as traits, but they're explicitly not intended to be expensive. Deref and DerefMut are intended solely to make smart pointers work as you'd want them to, and you're cautioned not to do something silly (they're safe Traits, so this can't make your program unsound, but e.g. misfortunate::Double deliberately has a silly implementation of these Traits and it hurts your head) AsRef strongly cautions you that it's intended to be cheap. For example AsRef allows us to take a String (which remember is just a Vec of bytes but we've promised it's UTF-8 text) and get a read only view into those bytes. Cheap.
I never said this was a Good Idea, and in fact specifically called out that it might not be. Nevertheless, it is a thing that you can do if you really want to.
Posted Aug 31, 2022 1:58 UTC (Wed)
by tialaramex (subscriber, #21167)
[Link]
This is one of those mirror image situations, you should implement From<SoccerMatch> on your FinalScore type, but you don't write From<T> or From<SoccerMatch> in the function signature which eventually might need the score, you write what you wanted, Into<FinalScore> instead. We're going to have a line like:
score: FinalScore = Into::into(some_parameter);
... so you can see some_parameter's type needs to be Into<FinalScore> to match.
This is idiomatic for the iterators, hence IntoIterator but it would be unusual to ask for Into<FinalScore> rather than just FinalScore unless you'd specifically designed all of the API this way. As I understand it, what the deferred computation people want for Python is a type which does not require you to be explicit up front in this way.
And that's why I don't think either C++ or Rust fit the bill. They can explicitly do this, but they aren't really designed to be able to implicitly defer computation, everybody involved needs to agree up front to this arrangement.
From late-bound arguments to deferred computation, part 2