Yes, the sieve algorithm does require remembering (implicitly, in the promises) the earlier primes. It shouldn't require remembering the earlier composites rejected by KEEP, though, and so the stack should grow only as fast as the number of primes computed, not the number of numbers checked.
On my computer, in streams 1.0, I can compute the first 450 primes (up to 3181) but crash when I try 500. In this test, it doesn't matter whether I store the stream of primes in a variable (remembering them all for sure) or just pipe it directly into SHOW STREAM.
But if it's remembering only the primes, not the composites, then 500 is way too small a number of primes to deserve to crash. So even in this version of the library, KEEP is remembering more than it needs to.
And the sieve example, much as I love it, is atypical in that later items depend on the earlier items all the way back to the beginning. We should be able to construct the infinite stream of Fibonacci numbers, for example, and display millions of them.
So (again, as you say, "from a user perspective, what... the outcome should (ideally) be") I don't agree with the necessary division of physical and mathematical stream implementations. The division is just between sieve and everything else, basically, and so I'd expect displaying the results of sieve to crash after maybe 100,000 primes. But I see no reason why Pythagorean triples should crash after four of them! I'd expect them to be able to run into the millions, because there's no reason to remember the early ones (supposing you don't store the whole stream in a variable).
Jens, every trainee teacher knows not to use words like "obvious." (We are taught not even to say "easy.") This just makes students to whom it isn't obvious (such as me) curl up and stop listening. I think if you can't teach me something, you should take that as a sign that you're expecting too much of less sophisticated users. I am the canary in the coal mine!
I actually do remember the discussion we had a long, long time ago about copying code because otherwise if users included a LIST block in their code and then mutated the list that that LIST call initialized, it'd mutate the procedure too. Is that what you're talking about?
But the issue right now, I think, isn't whether you have to copy code; it's whether all those copies have to live forever. Shouldn't the copy be garbage collected after the call finishes? Including when a tail call finishes?
I confirm that if I turn on "Live coding support" I can SHOW 1000 primes, probably many more but I didn't have the patience to try.