5 ms·
This "assignment is caching is bad" analogy does not hold any water. You get a result from a call to `foo(bar)`. You have to _do something_ with that result. O
by raquo 9y ago
This "assignment is caching is bad" analogy does not hold any water.
You get a result from a call to `foo(bar)`. You have to _do something_ with that result. One common thing you'd need to do is to call another function: _baz(foo(bar))_. But then you're just hiding the assignment inside a baz function call (the result of _foo(bar)_ will be available as a variable/constant inside of _baz_).
That doesn't so bad if you only need to do one thing with with the result of `foo(bar)`. Now what if you have to do something with that result twice. In this case all you've done is reduce the scope of a constant to be smaller than it needs to be, requiring you to make a duplicate `foo(bar)` call.
Now you're repeating yourself and you don't know anymore if you're conceptually dealing with the same result or if foo(bar) might produce a different result on second call. You removed philosophical/semantic meaning from your code and did not gain anything from it.
If you find yourself wanting/needing to "expire" variables that you define before you run out of scope, then the answer is a combination of:
1) use constants of immutable data structures, not variables or mutable structures
2) better name such constants so that you know what they represent
3) better manage scope and function size
In practice, the above is much easier to achieve than what you're proposing, and makes the code easier to read and maintain.
> The right way instead is to evaluate (or "re-evaluate") the function every time you need it unless you have a good reason not to (the only good reason is that the function is a bottleneck that affects the experience of the user)
That does not scale to using the coding paradigm that you're proposing application-wide. Your whole app will be one big bottleneck because it's doing a multiple of the computations that it needs to be doing, with no easy way out. I guess you can get away with that by throwing more money at your backend infra, but you can't do that on mobile or for web frontends or desktop apps.
- naasking 9y ago> You get a result from a call to `foo(bar)`. You have to _do something_ with that result. One common thing you'd need to do is to call another function: _baz(foo(bar))_. But then you're just hiding the assignment inside a baz function call (the result of _foo(bar)_ will be available as a variable/constant inside of _baz_). Unless the OP is arguing for call-by-name evaluation, which when you take his words literally, sounds like exactly what he's arguing for.
- raquo 9y agoCall-by-name is just syntactic sugar for anonymous functions. It has all the same problems. But more importantly, the whole premise is wrong. "Cache invalidation" for data that has an average lifespan of 30 lines of code in a single function is not a hard problem. Real cache invalidation is hard for reasons that don't translate to the case of ephemeral constants with properly limited scope.
- forkerenok 9y ago> Call-by-name is just syntactic sugar for anonymous functions. No, it's not. It defines different evaluation semantics.
- raquo 9y agoWhich are exactly equivalent to a function call, just with a different type, and a syntax without parens. "this will be re-evaluated every time you access it"
- forkerenok 9y agoI see what you meant now. Though it seems you are mixing notions of anonymous function and function as an argument of higher order functions (it doesn't have to be anonymous).
- quadcore 9y agoGood point. It's not really relevant for local variables I guess, because those caches are invalidated quite elegantly (you'll still find cases Im sure where the programmer took that too far). I dont have all the cases in mind but, for example, storing results in object members is common and more often than not, detrimental. Also, there is the events. Events are a caching mechanism as well. They are an optimisation and they are evil. Now don't get me wrong, if you have a bottleneck, events can be a great optimisation. The whole point being, FRP, while having some cool features, is mostly fixing bad programming practices.