Sending Values into a BLACKHOLE!

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. In fact, BLACKHOLE! is now a datatype you can put in a spec to mean "empty issue that is precisely #. It's not validated yet (it's a synonym for ISSUE!...we'll need type constraints before it can work). But it can help keep track of places that use this idea. For instance, SET:

>> set # 10
== 10

The truthiness of # helps write code that distinguishes the wish to opt-out of a behavior from the wish to opt-out of getting its result. Having SET error on blank helps you avoid calculations that may be unnecessary...so it works out perfectly:

 do-something: func [
     in
     /out [blank! word! path! blackhole!]
     <local> result
 ][
     process foo
      if bar [  ; unlike BLANK!, empty issue is truthy so branch runs
         result: process/more foo
         set bar result  ; blackhole SET is no-op (BLANK! would error)
      ]
 ]

Elegante.

2 Likes