Forum Discussion
A statement of truth or a wasted opportunity. Lambda helper functions reluctant to return 2D arrays.
PeterBartholomew1 lori_m Decided to mock-up my "array of LAMBDAs" suggestion since EVALUATE was revived in my memory. Perhaps I can configure this idea to work with MAKEARRAY similar to the proto-CORKSCREW previously shown, will give that a try later.
PeterBartholomew1 lori_m Success! I was able to avoid EVALUATE by using CHOOSE to create my array of LAMBDAs! Then by creating a COMPOSE lambda, I'm able to reduce an array of LAMBDA using COMPOSE. I think Peter will be able to run with this more quickly than I will, but I think its very promising!
- PeterBartholomew1Sep 18, 2021Silver Contributor
That is quite an achievement; an entire amortisation schedule in a cell. Rather like the numerical analogue of the ship in a bottle!
It might take me a while to assimilate the implications of this and related initiatives.
- lori_mSep 18, 2021Iron Contributor
Looks impressive! I'll need to see if there's a Python equivalent formulation to get my head around it. Regarding the last line:
=CHOOSE(SEQUENCE(,4), INDEX(amort,,1), INDEX(amort,,2)-INDEX(amort,,1), INDEX(amort,,1)-INDEX(amort,,3), INDEX(amort,,3))
This looks fairly readable when placed on separate lines but might sometimes be worth creating a LAMBDA function inline in such cases so as to replace INDEX(amort,,i) as col(i), say.
Another option, given people who use higher order functions would generally be familiar with matrices, might be:
=MMULT(amort,TRANSPOSE({1,0,0;-1,1,0;1,0,-1;0,0,1}))
- tbouldenSep 18, 2021Iron Contributor
This is a little less convoluted in terms of application, I think. Using the appropriate functions with SCAN, I get the minimal set of values that encapsulate the changes, then break those changes out into their own columns in the final step.
=LET( bal,100000, nper,120, rate,5%/12, pmt_,PMT(rate,nper,-bal), array_1, MAKEARRAY(nper,3,LAMBDA(i,j,j) ), fxns, CHOOSE(array_1, LAMBDA(x,x), LAMBDA(x,x*(1+rate)), LAMBDA(x,x-pmt_) ), amort,SCAN(bal,fxns,LAMBDA(acc,fn,fn(acc))), CHOOSE(SEQUENCE(,4),INDEX(amort,,1),INDEX(amort,,2)-INDEX(amort,,1),INDEX(amort,,1)-INDEX(amort,,3),INDEX(amort,,3)) )
- PeterBartholomew1Sep 17, 2021Silver Contributor
It is one thing to know that Lambda functions are first class citizens of the calculation and can be passed as arguments of other functions, it is another to achieve anything useful with the functionality. Congratulations. Presumably it is the MAKEARRAY that allows the formula to return the 2D array of results but following the formula is far from straightforward.
In connection with your other post, it does sometime seem odd having to create a Lambda function that does no more than the built-in function it implements [for me it might be SUMλ which is simply a restricted version of SUM]. It has yet to cause me grief though and, at present, I find the presence of the λ a useful reminder.
Meanwhile, I have been focussing on simpler problems on this forum. For example, to unpivot a 2D array
"UNPIVOTλ" = LAMBDA(grid, LET( fullList, REDUCE( , grid, APPENDλ), SORT(UNIQUE(fullList)) ))
where APPENDλ is defined by
"APPENDλ" = LAMBDA(list,value, IF(value="", list, LET( n, COUNTA(list), k, SEQUENCE(n+1), IF(k<=n, list, value)) ))
I have actually used REDUCE to run over a 2D array in row-major order to deliver value!
- tbouldenSep 17, 2021Iron ContributorOne thing that was on my wishlist that this re-emphasizes: if some legacy functions were converted to be LAMBDAs, we could have =REDUCE(UNIQUE,...)(team) instead of =REDUCE(LAMBDA(x,UNIQUE(x)),...)(team).
- tbouldenSep 17, 2021Iron Contributor
PeterBartholomew1 I've applied this REDUCE/COMPOSE construction to a modified version of your original problem. It's not as readable as the LET construction, but I think it will have applications for manipulations that frequently happen together.