It was only generally noticed recently and has been the subject of a couple of discussions.
People who read the help screens have known about it all along! People who read the manual too. :~)
There's a manual?
And people read it??
I have actually read the manual! (Not closely enough apparently, and not really all of it, I skipped around, ended up reading maybe half of it)
It's a really good book! Should be a best-seller.
Maybe if it were actually For Sale...
I 'enjoyed' it, I guess, I didn't really grok the different paradigm for object-oriented. I'm stuck in C++.
Neither of Chapters 7 and 8?
( ... re-looking it up... )
VII.E makes a distinction between class/instance OOP vs prototyping OOP. That broke my brain a little. I haven't put in the work to dig into that distinction, which seems important.
OK now I see it in the help screen for 'for item in list' (autofilling empty parameter with loop variable). However, 'for i in lo# to hi#' doesn't do that. Any special reason?
History and pedagogy.
Numeric FOR has a long history, all the way back to the Fortran DO loop. Through all that time, it has had a variable name as part of its syntax. Everyone is used to that. And nobody thinks of the instructions in the range of the FOR as constituting a procedure, so there's no question about actual arguments vs. formal parameters.
By contrast, FOR EACH ITEM is part of a package with the higher order functions MAP, KEEP, and COMBINE. (FIND FIRST came later.) In the HOFs it's clear, and it's something we want to teach, that the thing you're doing for each list item is calling a procedure. In the traditional lambda notation, you would provide a formal parameter and use it inside the function:
But in trying to teach these ideas to kids, all that notation was just in the way, and made HOFs scary to use.
So instead I took inspiration from my New Math childhood, when teachers learned that if you show an eight-year-old x+3=7 and ask what x is you're likely to get a blank stare, but if you show them ⃞+3=7 and ask "what number goes in the box, they can answer with ease. So the empty slot in is meant to be like that empty box: It just begs to be filled with some value.
(We also, unfortunately, inherited from Scratch the (imho bad) idea that an empty input slot means zero. Sometimes this leads to misunderstandings, especially among users who have graduated to Snap! from Scratch.)
So, initially FOR EACH ITEM didn't have an upvar; the word "item" was just text. My colleague Dan Garcia insisted that making it an upvar would make the block easier to use. I resisted for a while but it turned out that Jens agreed with Dan so I was outvoted.
So now we have both notations in FOR EACH ITEM. People like me who think FOR EACH ITEM is a lot like MAP can use empty slots, and people who think it's a lot like FOR can use the upvar.
I'm gonna make this a FAQ.
Awesome, thx for the detailed explanation.
I saw 'upvar' and thought 'that's a cool term for this', then at the end you said 'people who think it's a lot like FOR can use the upvar'. My intuition for 'upvar' was there's no regular var in there (it's an empty slot), just look up to see what it must be referring to -- it's an upvar. But I guess not.
Regardless of terminology, I'm excited to use empty-slot-style for block, as not just a cool shortcut, but a launching off point for keep/combine/map
We still would like a more self-explanatory name. It's called an upvar because regular inputs pass information from the caller down into the procedure, but with an upvar, the procedure is passing information up to the caller.
Why? What's automatic about it?
If we're talking about the same one, what goes into the empty slot is automatic. You don't have to manually drag the loop var into the slot.
Oh, I see, no, the I in the numeric FOR and the ITEM in the FOR EACH ITEM are upvars. The called procedure (FOR or FOR EACH) puts a value into that variable that the caller can then use.
It is a variable that represents an "output" of the proc/block, or a variable that is also accessible outside the proc/block
"UPvar" explicitly refers to calll stack/tree. So it is not that intuitive for beginners.
Also, there is no hoisting, so to being intuituve rather "downvar" or "aftervar" should be used
I'd rather have a name that didn't specify a direction at all. I mean, this is a really stupid example, but imagine we called it a "gift" variable, with the story that the block makes a gift of a value to its caller. Something like that, but not stupid.