Working With Truthy BLANK! (in SPLIT-PATH Tests)

The current re-imagining of the concept of truthy/falsey involves the idea that anything you can put into a block is truthy. That includes BLANK!.

~null~ isotopes are falsey, and will REIFY to be ~null~ which can be somewhat clumsy-looking.

But consider some test cases for seeing how SPLIT-PATH works, looking a bit like this:

split-path-tests:  [
    %foo                            [_ %foo]
    %/c/test/test2                  [%/c/test/ %test2]
    %/c/test                        [%/c/ %test]
    %//test                         [%// %test]
    %/test                          [%/ %test]
    %//                             [%// _]
    %./                             [%./ _]
    <...etc...>
]

SPLIT-PATH is a multi-return routine, which gives back two values: the path and the filename. But if one or the other is missing then that component will be null, which is useful for testing with IF (or using DEFAULT with).

But if we just blindly changed the tests to reify, it would become less legible:

split-path-tests:  [
    %foo                            [~null~ %foo]
    %/c/test/test2                  [%/c/test/ %test2]
    %/c/test                        [%/c/ %test]
    %//test                         [%// %test]
    %/test                          [%/ %test]
    %//                             [%// ~null~]
    %./                             [%./ ~null~]
    <...etc...>
]

However...with blanks being truthy, this means you that you can take a variable which may be null and turn it into a blank, like this:

reduce [any [path _] any [file _]]

That's rather succinct! Probably so succinct that it doesn't need its own native to express.

(I thought it was neat.)

1 Like

As a further note, I borrowed the tests for SPLIT-PATH from a Red issue.

And I want to say how bad historical Rebol/Red SPLIT-PATH seems to be!

Instead of giving you a directory and an optional file, you get the last directory fragment if there is no file part:

rebol2>> split-path %/c/rebol/tools/test/test.r
== [%/c/rebol/tools/test/ %test.r]  ; seems reasonable...

rebol2>> split-path %/c/rebol/tools/test/
== [%/c/rebol/tools/ %test/]  ; what?

rebol2>> split-path http://
== [http:/ %/]  ; seriously?

hiiamboris sums up my opinion, which is that you should never get a directory back for the file part.

So that is the Ren-C behavior:

>> [file dir]: split-path %/c/rebol/tools/test/
== ~null~  ; isotope

>> file
== ~null~  ; isotope

>> dir
== %/c/rebol/tools/test/

It uses multiple return values instead of returning a block. So there had to be a decision about which would be the primary and secondary results. It's a tough call, but I felt like splitting out the filename as the first result was probably the better option. You can of course use "circling" to get the directory instead without having to name a variable:

>> [_ @]: split-path %/c/rebol/tools/test/
== %/c/rebol/tools/test/

There was some debate about whether a null (none) signifier was better than coming back with an empty file like %"" to help with joining the parts back together. Historical #[none] doesn't have the voidability through MAYBE and just tends to create garbage. Oldes complains about having to remember to write the likes of any [file %""] to work around the problems:

rebol2>> join %/c/rebol/tools/test/ none
== %/c/rebol/tools/test/none  ; d'oh

But Ren-C has what I believe is just the right mix of caution on this... giving you a null that can be tested for truthiness, as well as alerting you to the absence if you try to use it...all while being able to easily MAYBE it into a void that can systemically act like emptiness:

>> [file dir]: split-path %/c/rebol/tools/test/

>> combined: join dir file
** Script Error: Invalid use of ~null~ isotope

>> combined: join dir maybe file
== %/c/rebol/tools/test/

>> file: join file %".temp"
** Error: JOIN does not allow null for its BASE argument