• Privacywetgeving
    Het is bij Helpmij.nl niet toegestaan om persoonsgegevens in een voorbeeld te plaatsen. Alle voorbeelden die persoonsgegevens bevatten zullen zonder opgaaf van reden verwijderd worden. In de vraag zal specifiek vermeld moeten worden dat het om fictieve namen gaat.

Uncalled lambda's (thunks).

JEC.

Terugkerende gebruiker
Lid geworden
27 feb 2019
Berichten
4.661
Office versie
365
Voor geïnteresseerde lezers, die niet bang zijn om zich ergens in vast te bijten, heb ik een uitdagend onderwerp.
Ik kwam laatst een techniek tegen waarbij gebruik werd gemaakt van uncalled lambda's, ook wel thunks genoemd. Dit zijn functies zonder parameters, welke je later aanroept.

Het gebruik hiervan kan in bepaalde situaties efficiënter zijn dan 'reguliere' formules. Bijvoorbeeld in accumulerende formules, waarbij tussentijds een waarde wordt opgeslagen, ga je verschil merken. Los van snelheid, levert het je ook mogelijkheden op om bepaalde kwesties in één dynamische array op te lossen.

Ik zal een poging doen om het uit te leggen adhv een voorbeeld;
Als voorbeeld neem ik de MAP functie. Deze functie geeft in basis het formaat van de array terug die je opgeeft. Geef je 1-dimensionaal, krijg je 1-dimensionaal. In de bijlage staat een situatie waarbij je via de MAP functie, in combinatie met deze "thunks", een 2-dimensionale array terugkrijgt, terwijl ik een 1 dimensionale invoer in de MAP functie.

Code:
=LET(
   THUNK; LAMBDA(a;b;LAMBDA(x;CHOOSE(x;a;b)));
   arr; THUNK(MAP(TAKE(H2#;;1);TAKE(H2#;;-1);THUNK); BYCOL(D2:F28;LAMBDA(x;LAMBDA(x))));
   MAP(arr({1}); arr({2}); LAMBDA(rep;col; SUMIFS(col(); A2:A28; rep(1); B2:B28; rep(2); C2:C28; ">="&DATE(H1;1;1); C2:C28; "<="&DATE(H1;12;31))))
)

In de "arr" regel roep je de lege choose functie aan en plaats je een verticale vector én een horizontale vector. De choose geeft hierdoor een 2-dimensionaal bereik terug voor iedere regel. De BYCOL functie fungeert zelf ook als een 'uncalled lambda', omdat deze geen parameter meekrijgt. In de laatste regel MAP je door de 2-d arrays, bestaande uit functies (en dus geen waarde!). Wat opvalt, is dat col() wordt geaccepteerd in de SUMIFS, omdat het een range is. Je hebt nu dus één dynamische array formule, waar je normaal voor iedere cel een eigen formule nodig zou hebben.

Ik durf te wedden dat meerdere mensen hier enthousiast van worden! ;)
 

Bijlagen

Een ander simpeler voorbeeld, waarbij je de twee verticale vectoren binnen de MAP omzet naar 1 functie. Later kun je de huidige waarde én de nieuwe waarde oproepen vanuit de "uncalled lamda"

Code:
=LET(
   THUNK;LAMBDA(a;b;LAMBDA(x;CHOOSE(x;a;b)));
   ar;MAP({"A";"a";"e";"i";"o";"u";"l";"S";"s";"y"};{4;"@";3;"!";0;2;1;5;"\$";7};THUNK);
   REDUCE("My Admin Password";ar;LAMBDA(s;c;REGEXREPLACE(s;c(1);c(2))))
)
Bericht automatisch samengevoegd:

Ander voorbeeld met TEXTSPLIT. Deze functie werkt alleen dynamisch als je één cel invoert. Bij invoer van een range krijg je alleen één kolom terug.

Neem als voorbeeld in A1:A4 deze data.
a,b
a,b,c
a,b,c,d,e,f
a,b,c,d

TEXTSPLIT(A1:A4;",") zal 1 kolom met 4x "a" teruggeven.

Onderstaande formule maakt weer gebruik van een 'thunks', waarbij de verschillende outputs vanuit textsplit als functies worden "gestacked". Daarna worden deze uitgelezen door er met REDUCE langs te lopen.

Code:
=LET(
thunk;LAMBDA(x;LAMBDA(x));
ar;MAP(A1:A4;LAMBDA(a; thunk(TEXTSPLIT(a;","))));
IFERROR(DROP(REDUCE("";ar;LAMBDA(s;c;VSTACK(s;c())));1);"")
)


Om een beeld te geven hoe je de verschillende rijen één voor één uit kan lezen (hier wordt functie 3,ofwel rij 3, uitgelezen. Je plaatst () achter de index omdat de functie geen parameters heeft.
Code:
=LET(
thunk;LAMBDA(x;LAMBDA(x));
ar;MAP(A1:A4;LAMBDA(a; thunk(TEXTSPLIT(a;","))));
INDEX(ar;3;1)()
)


Tot slot
Mocht je deze uitgebreide TEXTSPLIT functie willen hergebruiken, kun je het zo in je name manager plaatsen, met als naam bvb TEXTSPLITλ. Je bent zo vrij in het kiezen van je delimiter.

Code:
=LAMBDA(range; delimiter;
    LET(
        thunk; LAMBDA(x; LAMBDA(x));
        ar; MAP(range; LAMBDA(a; thunk(TEXTSPLIT(a; delimiter))));
        IFERROR(DROP(REDUCE(""; ar; LAMBDA(s; c; VSTACK(s; c()))); 1); "")
    )
)


Uiteindelijk kun je dit probleem ook anders oplossen. Bovenstaande is uiteraard puur ter illustratie:
Code:
=IFERROR(TEXTBEFORE(TEXTAFTER(","&A1:A4&",";",";SEQUENCE(;MAX(LEN(REGEXREPLACE(A1:A4;"[^,]";""))+1)));",");"")
 

Bijlagen

Laatst bewerkt:
Terug
Bovenaan Onderaan