So I had the idea that do [] would be conceptually nothing, but represented in some "ornery" reified form. I was going to represent this with a ~void~ isotope.
But the new revelation I had was that ~void~
isotopes are best if they are so "unstable" that they disintegrate immediately, only visible with the detector of a ^META step. Won't rehash the good reasons for that here:
Pure vs. Impure Invisibility: Do We Need Both?
This doesn't have to crush the idea: ~none~ isotopes can fulfill the role previously theorized for the ~void~ isotope. Because isn't that essentially what PRINT returning a ~none~
isotope means? "I don't have a useful result, I'd be invisible except for the fact that might be confusing...and someday I might want to have a result that means something."
But ANY and ALL no longer need to vaporize ~void~ isotopes... they vaporize themselves. So this needs to be revisited:
"I think ANY and ALL are the kinds of construct that become more interesting if they vaporize ~void~ isotopes...and if ALL returns a ~void~ isotope itself if its contents all vaporize!"
"The idea this brings back is the concept of having a third option for value-returning functions... so truthy, falsey, and "opt out". But opting out is not conflated with nullness or unsetness, and it doesn't force unsafe "vanishing" semantics."
It turned out to be a refreshing simplification when I ripped out the weird code in ANY and ALL to try and facilitate treating ~void~ isotopes as invisible. 
If you wish, you could write a version of ANY that actually vanished if it got a block of nothingness.
>> 1 + 2 vanishable-any [1020 null]
== 1020
>> 1 + 2 vanishable-any []
== 3
But I think we're likely better off making vanishing of ~none~ isotopes explicit, akin to what used to be called "DEVOID" when ~void~ isotopes were reified/ornery:
>> ~none~
== ~none~ ; isotope
>> 1 + 2 ~none~
== ~none~ ; isotope
>> 1 + 2 none-to-void ~none~
== 3
>> any []
== ~none~ ; isotope
>> 1 + 2 none-to-void any [1020 null]
== 1020
>> 1 + 2 any []
== ~none~ ; isotope
>> 1 + 2 none-to-void any []
== 3
(NONE-TO-VOID is not a perfect name...but I'd consider it a better choice than DENONE. Other ideas welcome. VANISHABLE?)
You could have a corresponding construct which turned ~none~ into NULL. Notice that Rebol2 and Red both decided that any [] should be their concept of BLANK! (e.g. legacy "none"). If you wanted something akin to that via a "NONE-TO-NULL", you could have it:
>> any []
== ~none~ ; isotope
>> none-to-null any []
; null
What About The "Loop Control Protocol"?
I think this policy makes reasonable sense for loops that never run:
>> while [false] [1 + 2]
== ~none~ ; isotope
Though it aliases with loops that return none incidentally from their bodies:
>> repeat 1 [print "Remember PRINT returns ~none~ isotope"]
Remember PRINT returns ~none~ isotope
== ~none~ ; isotope
If that's a problem for you then you can force some other return result from the loop body:
>> repeat 1 [print "Control your result", true]
Control your result
== #[true]
NULL is still the unique signal to say the loop encountered a BREAK, which makes it easier to make composite loops that are sequences of other loops.
But there's no unique signal to say the loop never ran...only that the overall loop operation "provided no meaningful result". This can play well with NONE-TO-VOID and NONE-TO-NULL
Today's Loop Story Gets Even Better...
Consider my classic example of a composite loop that actually iterates over two collections:
>> for-both x [1 2] [3 4] [print ["x is" x], <result>]
x is 1
x is 2
x is 3
x is 4
== <result>
>> for-both x [1 2] [3 4] [print ["x is" x], if x = 2 [break]]
x is 1
x is 2
; null
>> for-both x [] [] [print ["x is" x], <result>]
== ~none~ ; isotope
Trying to write something like FOR-BOTH in historical Redbol and get coherent behavior for BREAK for an arbitrary loop body is effectively impossible. (If anyone wants to troll Red, ask them how to do it and watch them give you scrambled broken solutions.) But modern Ren-C has it covered!
for-both: func ['var blk1 blk2 body] [
unmeta all [
meta for-each :var blk1 body
meta for-each :var blk2 body
]
]
This isn't that hard to understand: Remember that META leaves NULL as NULL...turns isotopic BAD-WORD!s into plain BAD-WORD!s...and quotes all other values one level. So here you're getting a pass through of non-null values, with NULL able to skip past the second loop if a break is signaled in the first loop.

(Actually needs a small tweak because plain BAD-WORD! is neither true nor false at this time and would need to be truthy, but I will make that change given this new obvious indicator they must be truthy...they're ornery enough by not being accepted as an argument to things like APPEND.)
So That Settles It
>> first [~none~]
== ~none~
>> if (first [~none~]) [print "plain BAD-WORD! now truthy."]
plain BAD-WORD~ now truthy
>> ~none~
== ~none~ ; isotope (not displayed by console)
>> if ~none~ [print "non-meta arguments can't be isotopes"]
** Script Error: if needs condition as ^META for ~none~ isotope
>> print "The die is cast"
The die is cast
== ~none~ ; isotope (not displayed by console)
>> do []
== ~none~ ; isotope (not displayed by console)
>> while [false] [<never-runs>]
== ~none~ ; isotope (not displayed by console)
We'll have to debate whether it's a good idea for REDUCE to allow ~none~ isotopes to be converted into plain ~none~ BAD-WORD!s without you asking to do so explicitly:
>> reduce [1 + 2 print "Good or bad idea?"]
Good or bad idea?
== [3 ~none~]
The conservative decision would be to make people use some function like REIFY to get that.
In the end, the sum of the decisions involved in building the solution shows that persistence ultimately pays off... and the pursuit of non-softball problems like building a 100% correct FOR-BOTH out of two FOR-EACH loops has lent Ren-C its true power.