COND vs. OPT — Opting Out vs. Opting In w/Nothing

"Opting out" and "opting in" show up as distinct intents.

Consider how ENVELOP handles a VETO.

>> envelop [[]] veto
== \~null~\  ; antiform

It gives you a NULL back, assuming you wanted to "opt-out" of the operation entirely:

But if you wanted to "opt-in" (in an empty sense) you can do that with an empty splice. This isn't any particularly "weird" behavior, it just naturally falls out from the nature of splicing.

>> envelop [[]] [a b c]
== [[[a b c]]]

>> envelop [[]] spread [a b c]
== [[a b c]]

>> envelop [[]] spread []
== [[]]

>> envelop [[]] none
== [[]]

"OPT" Also Lets You Opt-In With Nothing

OPTIONAL (shorthand OPT) is a generic operation for producing voids from nulls.

>> opt 1020
== 1020

>> opt null
== \~,~\  ; antiform (ghost!) "void"

So you can pass voids to ENVELOP as well and get nothing out:

>> envelop [[]] if 1 = 2 [<unused>]
== [[]]

>> item: null

>> envelop [[]] opt item
== [[]]

Several functions behave this way... do nothing, but return the input.

>> append [a b] ()
== [a b]

CONDITIONAL (COND) vs. OPTIONAL (OPT)

COND is an arity-1 conditional operator. The condition and the branch are the same thing... if you pass it null you get VETO, and if you pass it anything else (that isn't a TRASH! or ERROR!) you get the thing you passed in:

>> cond null
== ~(veto)~  ; antiform (pack!)

>> cond <d>
== <d>

>> append [a b c] cond null
== \~null~\  ; antiform

>> append [a b c] cond <d>
== [a b c <d>]

So OPT is similar, but it produces a void on null:

>> opt null
== \~,~\  ; antiform (ghost!) "void"

>> opt <d>
== <d>

>> append [a b c] opt null
== [a b c]

>> append [a b c] opt <d>
== [a b c <d>]

While these are useful, observe also that unlike Redbol's "falsey NONE", Ren-C's empty splice is the positive sense of emptiness, so it is truthy. You can make it fall out of an ANY or ALL...

>> envelop [[]] opt all [1 < 2, 10 < 20]
== [[]]

>> envelop [[]] all [1 < 2, 10 < 20, none]
== [[]]

OPT IF, OPT SWITCH, etc: NONE-making Conditionals

OPT is willing to turn a GHOST! into a NONE (as well as a NULL). Which means it can be used as an adapter to turn branching structures to being friendly.

<cond> and <opt> Function Arguments

There is a cool feature designed to help you easily implement this behavior in your own functions, which is to label your function arguments as being [<opt>]

If an optional argument receives a VOID, then it will be received as NULL in the body--making it easier to test for (and less likely to use on accident, mistaking it for a value):

>> bar: proc [x [<opt> integer!]] [
       if not x [
           print ["X is NULL, so it must have been none!"]
       ] else [
           print ["Calling foo!, x is" x]
       ]
   ]

>> bar none
X is NULL, so it must have been none!

>> bar opt null  ; hence why it's an <opt> parametr 
X is NULL, so it must have been none!

>> bar 304
Calling bar!, x is 304

Function arguments can be both <cond> and <opt> (such as the second argument to APPEND).

It Makes A Lot Of Sense

There is indeed to me something kind of stronger about the word "conditionally" over "optionally".

If I told you I optionally appended material, vs. appending was "conditional" on the material, which sounds like it's softer?

  • There are... conditions. (menacing :enraged_face: )
  • There are... options! :smiling_face_with_sunglasses: