For starters:
That's the value of the CALL,
no matter who's calling CALL. When the function being called is >, I'd argue that that's what the user wants, since lists aren't ordered, as numbers are, and so there's no right answer to "is this list greater than 1?"
(See that unsightly space between the 1 and the question mark? That's because the font is properly making digits monospaced, but it's a sans serif font, so there's no way for it to make the 1 actually take up the same space as a 5.)
If the predicate were = instead of >, there wouldn't be such an obvious right answer, because lists are in its natural domain. We are in fact conservative about this, and don't hyperize =. We do hyperize arithmetic operators and Boolean operations. We don't hyperize custom blocks, although the code in the block can check for a list as input. (Maybe we should have a HYPERIZED primitive that takes a function as input and reports a hyperized version, to make that easier. There's one in the APL library.) Then there's JOIN, which bizarrely does consider lists to be in its natural domain. Especially now that we have a FLATTEN primitive, maybe we should reconsider that, although changing it at this point would be a flag day event.
Since KEEP FROM STREAM is built with CALL, it's not surprising that it has the same behavior. That doesn't necessarily make it right, of course. I think it is right, though, since, again, lists aren't in the natural domain of >. On the other hand, your example comes out less pleasantly if, as one might expect, the data structure were streams all the way down:
So if we're going to hyperize KEEP FROM STREAM, we have to protect streams from being treated as lists. :~(
As for the primitive KEEP, it doesn't have to worry about protecting streams, so we can do whatever we want, except that since it's primitive that means doing whatever Jens wants, although as you say, changing its behavior would be a flag day, and Jens hates those. (Although we've done them in the past, notably when we changed the behavior of ITEM with a list as the index input.) There's an especially good case for hyperizing it if the list input is a uniform array:
I'll take all this up with the team.
Command IF, not hyperized, takes the view that anything that isn't False is true (as in Scheme), except that, regrettably, what it really does is say that anything that isn't Javascript-falsy is true. So in particular the list (True False) is true. One could argue that we should throw an error instead, but we're unlikely to change that at this late date.
Reporter IF, however, is hyperized, so given the list (True False) it turns True into True and False into False.
The difference between the two IFs is consistent with our general philosophy that only reporters are hyperized, although we recently introduced an exception, iirc, and I'd remember which command it is if I were more awake. Also, how would we hyperize command IF? Start a thread for each item? Presumably the predicate would report different values for different items, as in your example.
I'm aware that one of my flaws is overengineering things, but still, I'd be happier if users could answer some of these questions for themselves. One way to do that would be to have an ATOMIC LIST primitive, just like LIST except that it flags the list as exempt from being descended into by hyperization. IN FRONT OF and ALL BUT FIRST OF would preserve the flag. So would KEEP, and probably so would MAP, although I'd want to think more about that when awake. But I'm betting Jens will say that that would slow things down too much.
I'll look at your other message tomorrow.