This is a very old question on purity and side-effect that seems to have reached a certain kind of agreement with Monads.
Lots of papers treat this issue. Some suggested Effects Typing, some Continuations, then the Haskell guys figured
out that with type classes they could create a polymorphic monadic bind and did the trick.
But I think that what you say doesn't apply to Smalltalk because it's dynamically typed.
How would you know at compile time if a method does side-effects ....
What if a method called in a cascade does side effects , but the cascade itself seems pure ?
I think it's complex stuff...
Haskell does the "markings" (excuse the name) you talk about with monads
and anything "not marked" doesn't do any sideffects, it's pure.
By adding graph manipulation (reducing & updating) at runtime they evaluate functions "by name"
and than by updating the runtime graph they avoid re-computation.
In haskell basically every expression is in a [ ... ] (well sort of they use graph manipulation)
And it's sent the message value only if needed. And when the the value it's returned the block gets
removed and it's updated with the value... so no more need to evaluate it, if you need it again.
It's a powerful optimization ! Too bad that to get that you need to but Everything in a [ ... ]
(strictness analysis fixes that a bit).
But the price to pay is high in my opinion ...
functional becomes beautiful, but imperative stuff is a bit too hard ( not syntactically because of the 1 ton of syntax sugar)