I'm intrigued on why you would want those two calls to memoize separately? I'm sure there are reasons it could be needed, such that I'm not trying to argue against it. Genuinely curious to see a situation it would be desired.
You point out a good general problem that I find when blogging -- like, you don't want this, right? The whole premise is absurd; the point is not to memoize an expression, but rather to demonstrate that you can share values between compile-time and runtime. But in order to do this you need some specific example of the idea so that readers have something concrete to hold onto and generalize from. And then the difficulty is trying to present that specific example in a way that gets the general idea across, right, without the reader overfitting to the specific example you presented. It's hard! I don't think this one really succeeded.
I call that the curse of examples. Often conflated with "being in the weeds." Is frustrating, as people will jump on you with the X-Y problem style discussions. Which, fair that that is sometimes apt. Probably more often than makes sense, honestly.
Still, I did the callout that I did not mean that as an argument on if they really wanted it because I think it is fair to explore the intent as stated. And I appreciate how hard it is to make examples.
To your credit, you did explicitly call out your example in the blog post as something you wouldn't _actually_ want to do, so it didn't bother me. I've found that I'm more receptive to contrived examples to demonstrate a point if they aren't trying to hide the fact that they're contrived, so if I'm trying to convey a concept via example, sometimes I'll lean into the fact that the example is unrealistic to make it clear that the lack of utility shouldn't distract from the idea. As a silly example of this (see what I did there?), I might implement a trait with a `len` method that always returns 0 on strings to show how to resolve ambiguity when adding a method with name that a type already has in Rust.
a more plausible example than memoization is something like a polymorphic inline cache, where the cache can be very small and therefore fast to search but tends to be different at different callsites
Makes sense, I was thinking this is largely recreating L2 caches and such. Where you don't mind that they would memoize the same data, but the expectation is more that each caller would have a small subset they are specifically using over and over.
Sometimes it's nice to abstract a place where you need the answer from the way you determine the answer; that's basically why functions exist in the first place! Later on, if you decide that you want to tweak the way the implementation works, you don't need to do it literally everywhere.
Comments
I'm intrigued on why you would want those two calls to memoize separately? I'm sure there are reasons it could be needed, such that I'm not trying to argue against it. Genuinely curious to see a situation it would be desired.
You point out a good general problem that I find when blogging -- like, you don't want this, right? The whole premise is absurd; the point is not to memoize an expression, but rather to demonstrate that you can share values between compile-time and runtime. But in order to do this you need some specific example of the idea so that readers have something concrete to hold onto and generalize from. And then the difficulty is trying to present that specific example in a way that gets the general idea across, right, without the reader overfitting to the specific example you presented. It's hard! I don't think this one really succeeded.
I call that the curse of examples. Often conflated with "being in the weeds." Is frustrating, as people will jump on you with the X-Y problem style discussions. Which, fair that that is sometimes apt. Probably more often than makes sense, honestly.
Still, I did the callout that I did not mean that as an argument on if they really wanted it because I think it is fair to explore the intent as stated. And I appreciate how hard it is to make examples.
To your credit, you did explicitly call out your example in the blog post as something you wouldn't _actually_ want to do, so it didn't bother me. I've found that I'm more receptive to contrived examples to demonstrate a point if they aren't trying to hide the fact that they're contrived, so if I'm trying to convey a concept via example, sometimes I'll lean into the fact that the example is unrealistic to make it clear that the lack of utility shouldn't distract from the idea. As a silly example of this (see what I did there?), I might implement a trait with a `len` method that always returns 0 on strings to show how to resolve ambiguity when adding a method with name that a type already has in Rust.
a more plausible example than memoization is something like a polymorphic inline cache, where the cache can be very small and therefore fast to search but tends to be different at different callsites
Makes sense, I was thinking this is largely recreating L2 caches and such. Where you don't mind that they would memoize the same data, but the expectation is more that each caller would have a small subset they are specifically using over and over.
If you knew the answer, why did you ask the question?
Sometimes it's nice to abstract a place where you need the answer from the way you determine the answer; that's basically why functions exist in the first place! Later on, if you decide that you want to tweak the way the implementation works, you don't need to do it literally everywhere.
I thought of an answer after asking. Still curious if there are others.
so am i! fuck you, lupire
fib(3), fib(2), fib(6), fib(1000000), fib(9), fib(2), fib(8),...