Forum Discussion
BigSpill: A 97‑Function Excel LAMBDA Library for Dynamic Arrays
Two new functions have been added with the release of BigSpill v1.1.0 .
Triplewiseλ Generates a Cartesian product from 3 sets
Quadwiseλ Generates a Cartesian product from 4 sets
There's a lot of potential uses for these two functions in set generation and creating indices.
- djclementsSep 05, 2026Silver Contributor
Nice job with the Triple and Quad versions. I like how many of your custom functions are built upon one or more of your core array reshaping functions (e.g. Echoλ, Resizeλ, RepeatRowsλ, etc.). Would a Quint adaptation be written in a similar fashion to Quad?
For Cartesian products, I do tend to agree with m_tarler 's point that it may be easier to adapt Pairwiseλ for multiple arrays if it wasn't limited to vectors from the onset. Regarding 'fixed arity', I agree it can get a bit messy, what with LAMBDA's inability to declare the last argument as a ParamArray; however, with a reasonable number of optional array arguments, and a bit of LAMBDA trickery, it is possible to filter out omitted arguments. For example, a simple CrossJoinλ function and its CrossJoinMultλ companion might be:
CrossJoinλ = LAMBDA(array1,array2, HSTACK( CHOOSEROWS(array1,TOCOL(SEQUENCE(ROWS(array1))*EXPAND(1,,ROWS(array2),1))), CHOOSEROWS(array2,TOCOL(SEQUENCE(,ROWS(array2))*EXPAND(1,ROWS(array1),,1))) ) ); CrossJoinMultλ = LAMBDA(array1,array2,[array3],[array4],[array5],[array6],[array7],[array8], LET( vec, VSTACK(LAMBDA(array1),LAMBDA(array2),LAMBDA(array3),LAMBDA(array4),LAMBDA(array5),LAMBDA(array6),LAMBDA(array7),LAMBDA(array8)), arr, FILTER(vec,1-MAP(vec,LAMBDA(arg,ISOMITTED(arg())))), REDUCE(INDEX(arr,1,1)(),DROP(arr,1),LAMBDA(acc,val,CrossJoinλ(acc,val()))) ) );Which could be used as follows:
=CrossJoinMultλ(Animals,Letters,Colors,Numbers) // this would have the same basic effect as: =CrossJoinλ(CrossJoinλ(CrossJoinλ(Animals,Letters),Colors),Numbers).I've also toyed with the idea of a generalized ParamArrayλ function, e.g.:
CrossJoinParrλ = LAMBDA(array1,array2,[param_array], IF( ISOMITTED(param_array), CrossJoinλ(array1,array2), REDUCE( CrossJoinλ(array1,array2), FILTER(param_array,1-MAP(param_array,LAMBDA(arg,ISOMITTED(arg())))), LAMBDA(acc,val,CrossJoinλ(acc,val())) ) ) ); ParamArrayλ = LAMBDA(_1,[_2],[_3],[_4],[_5],[_6],[_7],[_8],[_9],[_10],[_11],[_12],[_13],[_14],[_15],[_16], VSTACK( LAMBDA(_1),LAMBDA(_2),LAMBDA(_3),LAMBDA(_4),LAMBDA(_5),LAMBDA(_6),LAMBDA(_7),LAMBDA(_8), LAMBDA(_9),LAMBDA(_10),LAMBDA(_11),LAMBDA(_12),LAMBDA(_13),LAMBDA(_14),LAMBDA(_15),LAMBDA(_16) ) );Which would look something like this:
=CrossJoinParrλ(Animals,Letters,ParamArrayλ(Colors,Numbers))But it's not very intuitive and would likely require a bit more error handling than usual to make it bullet-proof.
Just something to chew on. Kind regards.
p.s. PeterBartholomew1 said:
David's Braille challenge was interesting but I didn't get to a point where I could publish it. The OP deserved more discussion.
Sorry Peter, I should have given it more time before posting my solution, but it's still an open discussion. Feel free to post your complete solution there... I'd love to see it!
- Patrick2788Sep 05, 2026Silver Contributor
Yes, Quintwiseλ (or Fivewiseλ) would be nearly identical to Quadwiseλ. It would first create the Cartesian product of 4 sets and then resize the 5th set as needed. Triplewiseλ does much of the legwork in ordering the sets while Pairwiseλ stays simple.
I stop at 4 sets because maybe the need for a 5th set is rare? If one is looking to generate permutations with replacement, then that's another matter.
Generally, my thought process in development goes:
• Is there a need for this function? (If it involves 2D arrays, usually the answer is Yes!)
• Do I have the functions to write this elegantly? (If not, take a step back and develop a function that can be used again in other functions)
• Accept 2D arrays as shapes and avoid flattening
• Use Lambda helpers sparingly. MAP/MAKEARRAY on 2D arrays is potentially an expensive commitment. BYROW and SCAN are fast with 1D arrays. REDUCE for iterations is a last resort.
• Recursion can be helpful if used sparingly. The operand stack limit is still too low to favor it over dynamic programming.