# Thunking vs. Stuffing - Is there a difference?

Brass Contributor

# Thunking vs. Stuffing - Is there a difference?

When I mentioned the idea of stuffing to @Peter Bartholomew in a different context, he asked me what the difference was between stuffing and thunking.  I did not have an immediate answer for him and haven't had the chance to come up with one.  In the meanwhile, I am curious if any of you have an opinion.

Here are my two primary definitions:

A "thunk"  -  lambda(x, lambda(x))

"Stuffing" -

1) (the preferred version on my view) lambda(x, lambda(choice, choose(1, x))

or

2) (the thunk like version) lambda(x, lambda(choose(1,x))

The way they are created and have their values returned is as follows:

For the thunk:

``````=LET(
value, SEQUENCE(3,3),
thunk, LAMBDA(x, LAMBDA(x)),
thunk1, thunk(value),
thunk1_return, thunk1(),
thunk1_return)``````

For the preferred "stuff"

``````=LET(
value, SEQUENCE(3,3),
stuff, LAMBDA(x, LAMBDA(y, CHOOSE(1, x))),
stuffed_pref1, stuff(value),
stuffed_pref1_return, stuffed_pref1(5),
stuffed_pref1_return)``````

Where stuffed_pref1 can take any value (which is taken advantage of in other contexts).

Here is an example of how I use stuffing for stacking dynamically generated arrays and an edited excerpt from my note to him.  You'll notice that I include an "unstuff" lambda that exposes the previously stuffed element.  In this way, I now have a simple verb to describe the process and make explicit what is going on rather than relying on potentially ambiguous usage of variable_name = thunk(element) and variable_name() to guard and unguard an element.
______________

For the sake of brevity, here is a reduced version of some of the thinking. I hope my variable names make it clear what is going on, but here is a quick description - I encourage you to change the last line to each of the variable names.

First, I define the two base functions - "stuff" to guard an array/element and "unstuff" to unguard an array/element.

Second, I create two arrays of three elements (one as a row, and the other a column).

Third, I demonstrate the stuffing and unstuffing of these arrays - when stuffed you get a calc error, when unstuffed you get the array back.

Fourth, I stack the two guarded arrays and then demonstrate that by stuffing the stacked guarded arrays, I create a list of arrays that can be passed around and itered over (not to mention be expanded, sliced, etc.)!

Fifth, I give you the "secret" iter formula that you can parametrize to accept any function you wish to iter over, but I did not want to overwhelm you with yet another abstraction.

Sixth, I iter over the two-element list and vstack the original arrays expanded to have the same width. This is the result you see if you just copy/paste the formula.

Seventh, I create a third array (which is dynamically sized) add it to the original two element list, and then iter over the new three element list.

In my own module I obviously have these various functions named and segregated as discrete lambdas, but I wanted you to be able to just paste the formula as is and see the magic. Using this method, you can completely replace excel's "groupby" and "pivotby" functions with vastly better customization options. I can, for instance, filter a two-dimensional array by multiple options, pivot by whatever I like, and add "custom" columns to the end - all with specifiable column names, row "totals", and column totals. I can also sort by a desired column and will ultimately be able to sort by multiple columns.

``````=LET(
ex_array_row, {2, 3, 4},
ex_array_col, {"a"; "b"; "c"},
stuff, LAMBDA(target_array, LAMBDA(y, CHOOSE(1, target_array))),
unstuff, LAMBDA(stuffed_target_array, stuffed_target_array(1)),
stuffed_ex_array_row, stuff(ex_array_row),
unstuffed_ex_array_row, unstuff(stuffed_ex_array_row),
stuffed_ex_array_col, stuff(ex_array_col),
unstuffed_ex_array_col, unstuff(stuffed_ex_array_col),
row_with_stuffed_elements, HSTACK(stuffed_ex_array_row, stuffed_ex_array_col),
THIS_IS_A_LIST_OF_ARRAYS, stuff(row_with_stuffed_elements),
secret_list_iter, LAMBDA(LIST,
LET(
unstuffed_list, unstuff(LIST),
num, COLUMNS(unstuffed_list),
first_element, unstuff(INDEX(unstuffed_list, 1, 1)),
recursive_case, LAMBDA(self, n,
IF(
n = 1,
first_element,
LET(
current_element, unstuff(INDEX(unstuffed_list, 1, n)),
prior_elements, self(self, n - 1),
width, MAX(
COLUMNS(current_element),
COLUMNS(prior_elements)
),
result, VSTACK(
EXPAND(prior_elements, , width, ""),
EXPAND(current_element, , width, "")
),
result
)
)
),
result, recursive_case(recursive_case, num),
result
)
),
vstack_list_elements, secret_list_iter(THIS_IS_A_LIST_OF_ARRAYS),
ex_array_3, SEQUENCE(4, 4),
stuffed_ex_array_3, stuff(ex_array_3),
expanded_list, stuff(
HSTACK(unstuff(THIS_IS_A_LIST_OF_ARRAYS), stuffed_ex_array_3)
),
vstack_new_list_elements, secret_list_iter(expanded_list),
vstack_list_elements
)``````