FOSS Unleashed

Functions in XS that need two lists

One of the more curious things about XS is how nice it is to use when working with a list of things. Bash’s awkward syntax for its arrays is one of the reasons I stopped using it.
However, that is not to say that XS is without fault.

; fn twoLists {|A B|
    echo A \= $A
    echo B \= $B
}
; twoLists (1 2 3) (A B C)
A = 1
B = 2 3 A B C
; X = 1 2 3; Y = A B C
; twoLists $X $Y
A = 1
B = 2 3 A B C

When you give an XS fragment two lists, it passes those as a single list, and XS does not allow nested lists, so the separation between the two is completely removed.
However, XS is at least inspired by functional languages, and you can pass a fragment around, which is effectively a function. You can even have a fragment return a fragment, and closure behavior occurs.

My initial idea on how to solve this was to create a fragment that returns a closure that returns the list. Clojure has such a function, it calls it constantly.

fn %constantly {|list|
    result { result $list }
}

This does mean that the fragment that would need to use such behavior must always use it, so you have behavior like the following:

fn twoLists {|fnA fnB|
    let (A = <=fnA; B = <=fnB) {
        echo A \= $A
        echo B \= $B
    }
}

But at least that behavior is correct:

; twoLists <={ %constantly 1 2 3 } <={ %constantly A B C }
A = 1 2 3
B = A B C

It is however fairly unwieldly to make use of. However, functional languages also offer something called currying, which is something I’ve struggled to see the use of (XS and Javascript being the only languages where I do anything “functional”). So what did I actually need this for? List comparisons. I have two lists, and I want to get a list of what’s common between them. Using %constantly the fragment ends up looking like:

fn %common {|fn-p1 fn-p2|
    let (list = <=p1; res = ()) {
        for i <=p2 {
            if {~ $i $list} {
                res = $res $i
            }
        }
        result $res
    }
}

And calling it is the ugly echo <={ %common <={ %constantly 1 2 3 } <={ %constantly 2 3 4 } }, but if we rewrite it in a way that implements an emulated currying (I am aware that one could argue this isn’t currying):

fn %common {|listA|
    result {|listB|
        let (res = ()) {
            for i $listA {
                if {~ $i $listB} {
                    res = $res $i
                }
            }
            result $res
        }
    }
}

This new version looks a little cleaner in my opinion, and the calling behavior is both cleaner and potentially more useful!

echo <={ <={ %common 1 2 3 } 2 3 4 }

Obviously there’s a limit to how clean it can be with XS, but the fact that %common now returns a closure that is effectively “return what matches with my stored list” means I can save the fragment, then call it against multiple lists if needed.