Multiple return values have an interesting angle to them: the more values you request... the functionality you ask for might wind up being different.
Consider TRANSCODE. If you don't use multi-returns...or just ask for one return...you get the whole thing transcoded as a block:
>> transcode "<abc> <def>" ; plain behavior == [<abc> <def>] >> block: transcode "<abc> <def>" ; set-word! (follows usual rules) == [<abc> <def>] >> [block]: transcode "<abc> <def>" ; same behavior as `block:`, enforced == [<abc> <def>]
But if you supply it with a parameter in the second slot, it assumes you want /NEXT and will set that argument to the next position.
>> [value pos]: transcode "<abc> <def>" == <abc> >> pos == " <def>" >> value == <abc>
BLANK! gives you the ability to opt out of slots in the multiple return values that you don't want. But opting out doesn't just keep you from having to name a variable, it also un-requests the behavior...
>> [value _]: transcode "<abc> <def>" == [<abc> <def>] ; not a /NEXT, it was "revoked"
What if you want to request the behavior, but not have to bother with creating a variable to store it in? Well now that we are thinking # will be a shorthand for the immutable and not-appendable-to-strings "codepoint 0", it's a perfect choice:
>> [value #]: transcode "<abc> <def>" == <abc> ; only the /NEXT item
The value was requested but disappeared...into a black hole. I'm referring to # as "a blackhole" pending a better name, and you can typecheck for it with BLACKHOLE!