Forum Discussion
BigSpill: A 97‑Function Excel LAMBDA Library for Dynamic Arrays
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!
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.