Here is a teaser for List Extras...Totally untested.
I already have a collection of list routines in my List, Means and SortL programs.
ListExtras aims to eventually implement relevant functionality on the Prime comparable to DavidM's Listextensions for the HP48..HP50 family, to assist portability between the two platforms.
The current teaser should be considered untested pseudocode...
Code:
LOCAL CRID:="ListExtras API V0.01 © 2018";
LOCAL MORETEXT:="ListExtras by StephenG1CMZ on HP Prime\nInspired by DavidM's Listext on HP48-50.";
LOCAL MN:="ListExtras.";//Name
//IMPORT({List}); //Required
//IMPORT({Means,SortL}); //Required
LOCAL TP;
LOCAL ExBool:=0;//Request Exact//MEX
LOCAL NOVALERR:=ListIsEmptyError;//LPOP
LOCAL BADDIMERR:=ListIsEmptyError;
//Forward
LNMRL(LST);
EXPORT ABOUT()
BEGIN
MSGBOX(CRID);
MSGBOX(MORETEXT);
MSGBOX("An early teaser...\nTotally untested");
END;
TBD()
BEGIN
MSGBOX(MN+"TBD");
END;
EXPORT ArrangeFunctions()
BEGIN
END;
EXPORT LRLLD(LST)
//INVERSE ROTATE (=−1 ROT)
BEGIN
LOCAL HD:=LST(1);
RETURN CONCAT(ListAFTER(LST,1),HD);
END;
EXPORT LROLL(LST)
//ROTATE (=1 ROT)
BEGIN
LOCAL LAST:=LST(0);
RETURN CONCAT(LAST,ListBEFORE(LST,SIZE(LST)));
END;
EXPORT LROT(LST,ROTNUM)
//ROTATE A LIST NUM POSITIONS (NUM SIGNED)
//NEED -1 REPEATEDLY TBD
BEGIN
LOCAL II;
IF ROTNUM THEN
TBD();
FOR II FROM 1 TO ABS(ROTNUM) DO
IF ROTNUM>0 THEN
RETURN LROLL(LST);
ELSE
RETURN LRLLD(LST);
END;
END;
END;
RETURN LST; //NO ROT
END;
EXPORT LSWAP(LST,POSN1,POSN2)
//SWAP 2 ELEMENTS
BEGIN
LOCAL TMP:=LST(POSN1);
LST(POSN1):=LST(POSN2);
LST(POSN2):=TMP;
END;
EXPORT LSSR(LST,POSN1,POSN2)
//REVERSES PART OF A LIST, RETURNS WHOLE LST
//EXT: POSN>0 INCLUDED (NULL=POSN=0)
BEGIN
LOCAL TMP:=REVERSE(ListSLICE(LST,POSN1,POSN2));
LOCAL BEF:=ListBEFORE(LST,POSN1);
LOCAL AFT:=ListAFTER(LST,POSN2);
ListANS:=CONCAT(BEF,CONCAT(TMP,AFT));
RETURN ListANS;
END;
EXPORT LSHUF(LSTNUM)
//SHUFFLES LST
BEGIN
RETURN ListSHUFFLE(LSTNUM);
END;
EXPORT REV(LstStN)
//EXT: REVERSE LISTS STRINGS N
//THIS IMPLEMENT ALSO DOES SUBLISTS
//QUERY DO WE NEED? DOES BUILTIN REVERSE SAME?
BEGIN
TP:=TYPE(LstStN);
CASE
IF TP==TYPELST THEN RETURN REVERSE(LstStN); END;
IF TP==TYPESTR THEN TBD(); END;
DEFAULT
END;
END;
EXPORT EditFunctions()
BEGIN
END;
EXPORT LDDUP(LST)
//EDIT:REMOVE DUPLICATES
//EXT:SAME SEQ
//X:NATIVE SEEMS TO
BEGIN
RETURN ListREMOVEDUPLICATES(LST);
END;
EXPORT LHDTL(LST)
//EDIT: AKA LPOP. NULL=NOVAL ERR
//X: Tail in ListANS. NULL=ListIsEmptyError
BEGIN
RETURN ListHEAD(LST);
END;
EXPORT LINSR(LST,POSN,ITEMS)
//EDIT: INSERT ITEM(S) AKA LINSRT
//INSERTS 1 ITEM OR A LIST OF ITEMS
//QUERY: HOW TO INSERT 1 ITEM OF TYPE LST?
//EXT: POSN<2 NEEDS HANDLING
//X: EXT COMPATABILITY TBD
BEGIN
RETURN ListINSERT(LST,POSN,ITEMS);
END;
EXPORT LINSRT(LST,POSN,ITEMS)
//AKA LINSR
BEGIN
RETURN LINSR(LST,POSN,ITEMS);
END;
EXPORT LFIRST(LST,NUM)
//EDIT: RETURN FIRST ITEMS AKA LFRST
//GUARDS AND NEGATIVES TBD
//EXT: N<0 UNK ERR N==0 NULL
//X:NO ERROR YET
BEGIN
RETURN ListBEFORE(LST,NUM+1);
END;
EXPORT LFRST(LST,NUM)
//AKA LFIRST
BEGIN
RETURN LFIRST(LST,NUM);
END;
EXPORT LLAST(LST,NUM)
//EDIT: RETURN LAST ITEMS
//EXT: N<0 UNK ERR 0 NULL N>LST LST
//X: GUARDS AND NEGATIVES TBD
BEGIN
LOCAL POSN:=SIZE(LST)-NUM;
RETURN ListAFTER(LST,POSN);
END;
EXPORT LPICK(LST,GETLST)
//EXT:EMPTY GET=NULL
BEGIN
RETURN ListGETLIST(LST,GETLST);
END;
EXPORT LPOP(LST)
//EDIT: AKA LHDTL
BEGIN
RETURN LHDTL(LST);
END;
EXPORT LPOPR(LST)
//EDIT: POP LAST ITEM
//EXT: NULL=NULL AND NOVAL ERR
//X: ERR TBD
BEGIN
IF SIZE(LST) THEN
ListANS:=ListBEFORE(LST,SIZE(LST));
RETURN LST(0);
END;
ListANS:={};
RETURN {};
END;
EXPORT LPSHR(LST,ITEM)
//EDIT: PUSH ITEM TO RIGHT OF LST
//EXT: ITEMTYPE=LST:PUSH 1 ITEM NULLNULL={{}}
//X: TBD NULL GUARDS CF LPUSH
BEGIN
LST(0):=ITEM;
END;
EXPORT LPUSH(LST,ITEM)
//EDIT:ADD ITEM TO FRONT
//EXT NULLNULL={{}}
//TBD:NULL GUARDS DONT WORK
//LATER:USE GUARDS IN LIST
BEGIN
IF LST=={} THEN
RETURN {ITEM};
END;
IF ITEM=={} THEN
RETURN CONCAT({},LST);
END;
RETURN ListINSERT(LST,1,ITEM);
END;
EXPORT LRCL(LST)
//EXT:({A}) -> 5 IF A IS 5
//X: ({"2+3"}) -> 5 ==> NOT THE SAME
BEGIN
LOCAL II;
ListANS:={};
FOR II FROM 1 TO SIZE(LST) DO
ListANS(0):=EXPR(LST(II));
END;
RETURN ListANS;
END;
EXPORT LREPL(LST,TARGETLST,REPLLST)
//WHEN TARGETLSTn EXISTS IN LST
//REPLACE IT WITH REPLLSTn
//RETURN MODIFIED LST
//Hint: CALL ListREPLACE FOR EACH n
//QUERY: WHAT HAPPENS IF CHANGED TWICE
BEGIN
LOCAL II;
ListANS:=LST;
//Can this be more efIcient?
FOR II FROM 1 TO SIZE(TARGETLST) DO
ListANS:=ListREPLACE(ListANS,TARGETLST(II),REPLLST(II));
END;
RETURN ListANS;
END;
EXPORT LRMOV(LST,POSNS)
//EDIT: REMOVE ITEMS
//EXT: REMOVE MULTIPLE POSNS IGNORING DUPLICATE POSNS
//X: SINGLE POSN ONLY FOR NOW
BEGIN
IF TYPE(POSNS)==TYPELST THEN
TBD();
END;
RETURN ListREMOVEX(LST,POSNS);
END;
EXPORT GroupFunctions()
BEGIN
END;
EXPORT GrpLCLLT(LSTS)
//List Collate. INVERSE OF LDIST
BEGIN
LOCAL II,JJ;
LOCAL SIZE1:=SIZE(LSTS(1));
ListANS:={};
//REQUIRE ALL SIZES SAME
FOR II FROM 1 TO SIZE(LSTS) DO
IF SIZE1≠SIZE(LSTS(II)) THEN
RETURN "BAD DIM";//UNK ERR
END;
END;
//OK, COLLATE
FOR JJ FROM 1 TO SIZE1 DO
FOR II:=1 TO SIZE(LSTS) DO
ListANS(0):=LSTS(II,JJ);
END;
END;
END;
EXPORT LDIST(LST,NUM)
//DISTRIBUTE ITEMS INTO NUM SUBLISTS.INVERSE OF LCLLT. CF LSDIV
//EXT: NUM MUST EVENLY DIVIDE LISTSIZE. UNK ERR
//HINT REPEATEDLY CALL ListBEFORE
BEGIN
TBD();
END;
EXPORT LGRP(LST)
//GROUP REPEATED ELEMENTS IE NO DUPLICATS
BEGIN
RETURN ListREMOVEDUPLICATES(LST);
END;
EXPORT LRPCT(LST)
//LIST LGRP ELEMENTS AND COUNTS
//EXT: NULL={{},{}}
//X:DITTO
BEGIN
RETURN ListCOUNTS(LST);
END;
EXPORT LRPCTo(LSTVLSTF)
//INVERSE
BEGIN
LOCAL LSTV:=LSTVLSTF(1);
LOCAL LSTF:=LSTVLSTF(2);
RETURN ListUNCOUNTS(LSTV,LSTF);
END;
EXPORT LSDIV(LST,SUBSIZE)
//SPLIT A LIST INTO LISTS OF SIZE SUBSIZE. CF LDIST
//EXT: NO REMNANT. UNK ERR.
//HINT REPEATEDLY CALL ListBEFORE
BEGIN
TBD();
END;
EXPORT LXIL(LST)
//FLATTEN TOP LISTS
BEGIN
RETURN ListFLATTENTOP(LST);
END;
EXPORT LXILR(LST)
//FLATTEN LISTS RECURSIVELY
BEGIN
RETURN ListFLATTENALL(LST);
END;
EXPORT RSPLT(LstStN,RSIZE)
//RIGHT SPLIT Lst St Or N. SZ=IP(RSIZE)
//EXT:LST: RETURN 2 LISTS, RIGHT OF SIZE RSIZE
//SIMILARLY FOR ST AND N
BEGIN
TBD();
END;
EXPORT SPLIT(LstStN,LSIZE)
//SPLIT A Lst St OR N. (IE LSPLT CF RSPLT) SZ=IP(LSIZE)
BEGIN
TBD();
END;
EXPORT SLISTTo(LST)
//EXT:SAFE LST AVOIDING GARBAGE COLLECTION
//X: IRRELEVANT?
BEGIN
RETURN LST;
END;
EXPORT MakeFunctions()
BEGIN
END;
EXPORT MakeLASEQ(FRM,CHNG,NUM)
BEGIN
LOCAL XX;
RETURN IFTE(NUM>0,MAKELIST(FRM+(CHNG*XX),XX,0,NUM-1),{});
END;
EXPORT MakeLDSEQ(FRM,CHNG,NUM)
BEGIN
LOCAL XX;
IF CHNG==0 THEN
RETURN "NaN";//DIVBY0
END;
IF (TYPE(FRM)==TYPE(CHNG) AND TYPE(CHNG)==TYPEINT) OR ExBool THEN
RETURN IFTE(NUM>0,MAKELIST(exact(FRM/(CHNG^XX)),XX,0,NUM-1),{});
END;
RETURN IFTE(NUM>0,MAKELIST(FRM/(CHNG^XX),XX,0,NUM-1),{});
END;
EXPORT MakeLMSEQ(FRM,CHNG,NUM)
BEGIN
LOCAL XX;
RETURN IFTE(NUM>0,MAKELIST(FRM*(CHNG^XX),XX,0,NUM-1),{});
END;
EXPORT MakeLSEQ(CNT)
//Create CNT REAL integers
//Return Real integer (No N)
BEGIN
LOCAL XX;
RETURN ListANS:=IFTE(CNT,MAKELIST(XX,XX,SIGN(CNT),CNT),{});
END;
EXPORT MakeLSEQR(FRM,TOO)
//Create CNT REAL integers
//Return Real integer (No N)
BEGIN
LOCAL XX;
RETURN ListANS:=IFTE(TOO-FRM,MAKELIST(XX,XX,FRM,TOO),{});
END;
EXPORT MakeLMRPT(ITEMS,RPTCNT)
BEGIN
IF RPTCNT<0 THEN
RETURN {};//OR NEGATE
END;
IF TYPE(ITEMS)≠TYPELST AND RPTCNT==1 THEN
//GUARD AGAINST SINGLE ITEM ONCE NOT RETURNING A LIST
RETURN MakeLMRPT({ITEMS},RPTCNT);
END;
IF RPTCNT>1 THEN
RETURN CONCAT(ITEMS,MakeLMRPT(ITEMS,RPTCNT-1));
END;
RETURN IFTE(RPTCNT,ITEMS,{});
END;
EXPORT MathFunctions()
BEGIN
END;
EXPORT LMAX(LST)
//EXT: CAN ALSO MAX LISTS OF STRINGS
//EXT: NULL=INVALID DIM
//X: NUMERICS ONLY
BEGIN
//RETURN ListMAX(LST);
RETURN MAX(LST);
END;
EXPORT LMIN(LST)
//EXT: CAN ALSO MIN LISTS OF STRINGS
//EXT: NULL=INVALID DIM
//X: NUMERICS ONLY
BEGIN
//ListMIN NOT IMP?
RETURN MIN(LST);
END;
EXPORT LSUM(LST)
//HANDLES NULL
BEGIN
//RETURN ListΣLIST(LST);
END;
EXPORT LPROD(LST)
//HANDLES NULL
BEGIN
//RETURN ListΠLIST(LST);
END;
EXPORT SortFunctions()
BEGIN
END;
EXPORT KSORT(LST,KEYLST)
//EXT:NULL KEY RETURNS TARGET UNCHANGED
//EXT:NULL TARGET AND NON NULL KEY=BAD DIM
//RETURN 2 LISTS
BEGIN
RETURN SortByKeyLST(LST,KEYLST);
END;
EXPORT KSORTFUN(LST,KEYLST,KEYFUNC)
//Pysort implements sort functions
//NB The ext list sequence is not implemented
BEGIN
MSGBOX("Use SORTL.Pysort");
END;
EXPORT StringFunctions()
BEGIN
END;
EXPORT StringLOCASE(ST)
//EXT:ST
//X-ALSO LST
BEGIN
RETURN LOWER(ST);
END;
EXPORT StringUPCASE(ST)
//EXT:ST
//X-ALSO LST
BEGIN
RETURN UPPER(ST);
END;
EXPORT RPTCHR(ST,RPTCOUNT)
//QUERY: IN EXT IF STRING IS >1 CHAR
//IS THE COUNT THE NUMBER OF REPETITIONS OF STRING
//OR NUMBER OF CHARACTERS
//(REPETITIONS EASIER?)
//HINT I HAVE IMPLEMENTED THIS RECURSIVELY IN A PROGRAM
BEGIN
TBD();//BUT WHERE
END;
EXPORT TestFunctions()
BEGIN
END;
EXPORT LCNT(LST,ITEM)
//NB TO COUNT ITEM=LISTS SEE IMPLEMENT
BEGIN
RETURN ListCOUNTITEMS(LST,ITEM);
END;
EXPORT LEQ(LST)
//TST ALL ITEMS IN 1 LST ARE SAME
//EXT: NULL OR SIZE 1 RETURNS TRUE (NO NON-MATCHES)
BEGIN
LOCAL XX;
LOCAL TMP:=LST(1);
ListANS:=MAKELIST(TMP,XX,1,SIZE(LST));
RETURN EQ(LST,TMP);
END;
EXPORT MPOS(LstSt,ITEM)
//Find ITEM in Lst or St
BEGIN
IF TYPE(LstSt)==TYPELST THEN
RETURN ListFIND(LstSt,ITEM);
ELSE
TBD();
END;
END;
EXPORT MPOSL()
//AS MPOS BUT IF LSTn IS A LIST, MATCH IN THERE TOO
//BUT NOT FULLY RECURSIVEO JUST ONE LEVEL
BEGIN
TBD();
END;
EXPORT LNMRL(LST)
//EXT:NORMALISE COMPRESSES LST
//X:NOP
BEGIN
RETURN LST;
END;
EXPORT LSAME(LST1,LST2)
//EXT: IMPLEMENTS LMRL SAME
BEGIN
RETURN EQ(LST1,LST2);
END;
EXPORT ThatsAllFunctions()
BEGIN
END;
EXPORT LISTEXTRAS()
BEGIN
END;