The concept of "void means remove" has gotten more entangled, now that it's legal to put unstable antiforms in metavariables (and, presumably, meta-map entries as well).
>> m: make map! []
>> m.^key: pack [1 2]
== \~['1 '2]~\ ; antiform
>> m.^key
== \~['1 '2]~\ ; antiform
This means mapping to the empty pack of VOID (and presumably to GHOST!, or ERROR!) should be legal.
That doesn't mean a non-^META assignment of VOID can't mean "remove". But it would be a point of "inconsistency".
Though is it any more inconsistent than saying ^e: fail "msg"
is different from e: fail "msg"
... with the former storing an unstable ERROR! antiform, and the latter escalating the error to a panic?
Without some "assignment-based" mechanism to remove map keys, you'd have to use an operation that wasn't SET or a set-word. For instance, if UNSET were kept as a prefix operation:
unset $m.key
This requires branching your code in ways that aren't as pleasing as just being able to OPT your assignment out.
Rethinking "Wacky Packs"
I have proposed the wacky idea of using PACK! as a means of doing things like assignment-with-typechecking, using sub-band values (like a BLOCK! which is neither quoted nor quasi):
>> var: (typed [integer! tag!] 1020)
== \~[ [&[parameter! [integer! tag!]] '1020] ]~\ antiform
That could pretty clearly decay to the value minus the typecheck.
Then I floated similar ideas for unsetting things, using sub-band WORD! for example:
>> var: unset
== \~[ *unset* ]~\ antiform
That would also be not-quoted and not-quasi inside the pack...so it can be distinguished as a special signal. However, I wasn't sure what that should decay to (e.g. if you wrote any [x: unset ...])
But neither of these ideas would be effective for ^META assignment, because the meta assignment would just store the pack.
Why Be Any More Obtuse? Let VOID Unset Variables
I'm kind of feeling now like VOID in non-^META assignments should just unset variables. Then just live with the idea that ^META assignments can't be used to remove things.** You can't have it both ways.
Since VOID is an empty PACK!, this would be a change from the situation of getting a panic today when you try:
[x]: pack [] ; empty PACK! (definition of VOID)
Today the error guards you from misunderstandings, just as you're guarded against misunderstandings when you say:
[x y]: pack [1]
But the problem is, that if you go and start trying to invent workarounds for ways to "assign" the unset state (like ~[unset]~) that are any weirder than this, your weirdness creates new problems.
I think that I now believe that either VOID non-^META assignments should be the way that you get the unset state, or there just isn't an offered way to get the unset state through assignment.
Ergonomically, being able to get the unset state through assignment has a lot of advantages. And many assignments are not ^META.
I think it is worth it, to allow voids to unset variables--and remove them from maps--without having to write branching code to use a special removal operation. If you truly are writing something "full-band" that wants to do meta-assignment -or- unset the variable, I guess it's acceptable that then you have to branch your code to do either a meta-assignment or a non-meta void assignment (or use the UNSET function).
Meditation on True Unset
"Unsetness" is perpetually thorny.
The idea of true unset has been to create an out of band state which would defeat accesses by even meta variable access with ^VAR. You cannot specialize function arguments with the unset state... hence it's a state FRAME! variables can be in (present, but unset) but not one that's very friendly.
If FRAME! variables can be "present, but unset" what is it about MAP! keys that means they can't be present in an enumeration, but unset? Should object variables have this? Module variables?
If object variables can have the unset state, and you can get it just with a non-^META assignment to void, when would you write field: ~
vs. field: void
? Why prefer one over the other? At least one difference would be that ^field
would work on the trash-assigned-variable, but not on the void-assigned-hence-unset-variable... but how does that inform things more generally?
I'll just throw in a little reminder of why trash is distinct from void in other places, e.g. why PRINT returns trash and not void. The reason is that VOID opts out of too many things., and:
append data (... print "Hello"))
...should error, not be silent. TRASH!'s raison-d'etre is to throw wrenches in things, whereas VOID is silently accepted as an opt-out.
(So if anything, the current philosophy is backwards... VOID should silently unset a SET-WORD!, while TRASH should cause a panic on the assignment. Not that I believe it should, I'm just saying that if anything should be a panic, it's probably trash...not void.)
Back to the question: if VOID doesn't remove from MAP!, it's useless. But VOID can't remove fields from FRAME!, because you can't remove fields from frames--and it's not what we'd want it to do. You need to still be able to FOR-EACH enumerate a FRAME! to get at its keys, even if they're not assigned yet.
OBJECT! has the same underlying implementation as FRAME!--just an ordered set of slots in memory. Why would VOID assignment remove any of those slots from enumeration? LET variables start out life in the unset state...so why wouldn't a VOID assignment return them to that state?
It really seems like MAP! is just the odd one out here. But it's not storing variables, it's storing mappings. You can't bind into a map either. I guess we can say simply that the unset state is something only variables need to worry about preserving.
So Should You Declare "unassigned" Variables with field: ~
or With field: void
?

TRASH! is now truthy, by design, so using VOID means if you declare things in ANY or ALL, that would be skipped as a no-op, at least in the current imagining of ALL, that throws out voids:
eval wrap all [
x: y: z: void ; ALL throws out voids this would be no vote
...
]
But one problem with it is that it's not assigning void, so it's misleading. 
Reminder: Why Isn't VOID Was The Unset State?
Because several changes have come that are new, it's good to ask why Why isn't VOID as a Meta-Variable Assignment The "UNSET" state?
Where this starts to break is in FRAME! creation, where unspecialized slots look like they're assigned void:
>> f: make frame! subtract/
== &[frame! [
^value1: ~[]~
^value2: ~[]~
]]
The problem is, VOID is now used to opt-out of things. You couldn't then tell the difference between:
make frame! [foo void]
make frame! [foo]
This has been why the "truly unset" state has been important--something an evaluation cannot produce, yet a variable can represent (but never fetch with GET). I do note, though, that there's an advantage if void is allowed to set things to the unset state, that means there can be a difference:
&[frame! [
value1: ~[]~ ; non-meta assignment (value1 is unset)
^value2: ~[]~ ; meta-assignment (value2 is void)
]]
Guidance Still Hazy, But Mechanics Look Solid
It bothers me some to have x: void
be legal, because it looks like you've assigned void to the variable... when a non-^META assignment can't do that. This has been an error historically, and it feels misleading to make it a non-error.
However--as I've said--IF there is going to be a state that unsets variables through assignment, it doesn't make sense to use a state other than void (more generally, "missing pack slot"). There are too many questions opened up by using another state.
So as for the misleadingness... I could similarly say that it's misleading to do append [a b c] void and get back [a b c], "because you didn't really append void". No...because you can't append void to a block..but there is meaning applied to it anyway.
But when it comes to coherent source, this does make it seem better to assign things with ~
in general when you want to poison them. This works whether you're doing an assignment or a meta-assignment, and also has a smooth transition to if you want to use a labeled trash.