123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623(*
* ExtList - additional and modified functions for lists.
* Copyright (C) 2003 Brian Hurt
* Copyright (C) 2003 Nicolas Cannasse
* Copyright (C) 2008 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)#ifOCAML<407moduleStdlib=Pervasives#endifmoduleList=struct#ifOCAML<408type'at='alist#endifexceptionEmpty_listexceptionInvalid_indexofintexceptionDifferent_list_sizeofstringincludeList(* Thanks to Jacques Garrigue for suggesting the following structure *)type'amut_list={hd:'a;mutabletl:'alist}externalinj:'amut_list->'alist="%identity"letdummy_node()={hd=Obj.magic();tl=[]}lethd=function|[]->raiseEmpty_list|h::t->hlettl=function|[]->raiseEmpty_list|h::t->tletnthlindex=ifindex<0thenraise(Invalid_indexindex);letrecloopn=function|[]->raise(Invalid_indexindex);|h::t->ifn=0thenhelseloop(n-1)tinloopindexlletappendl1l2=matchl1with|[]->l2|h::t->letrecloopdst=function|[]->dst.tl<-l2|h::t->letcell={hd=h;tl=[]}indst.tl<-injcell;loopcelltinletr={hd=h;tl=[]}inlooprt;injrletrecflattenl=letrecinnerdst=function|[]->dst|h::t->letr={hd=h;tl=[]}indst.tl<-injr;innerrtinletrecouterdst=function|[]->()|h::t->outer(innerdsth)tinletr=dummy_node()inouterrl;r.tlletconcat=flattenletmapf=function|[]->[]|h::t->letrecloopdst=function|[]->()|h::t->letr={hd=fh;tl=[]}indst.tl<-injr;looprtinletr={hd=fh;tl=[]}inlooprt;injrletrecdropn=function|_::lwhenn>0->drop(n-1)l|l->llettakenl=letrecloopndst=function|h::twhenn>0->letr={hd=h;tl=[]}indst.tl<-injr;loop(n-1)rt|_->()inletdummy=dummy_node()inloopndummyl;dummy.tl(* takewhile and dropwhile by Richard W.M. Jones. *)letrectakewhilef=function|[]->[]|x::xswhenfx->x::takewhilefxs|_->[]letrecdropwhilef=function|[]->[]|x::xswhenfx->dropwhilefxs|xs->xsletrecunique?(cmp=(=))l=letrecloopdst=function|[]->()|h::t->matchexists(cmph)twith|true->loopdstt|false->letr={hd=h;tl=[]}indst.tl<-injr;looprtinletdummy=dummy_node()inloopdummyl;dummy.tlletfilter_mapfl=letrecloopdst=function|[]->()|h::t->matchfhwith|None->loopdstt|Somex->letr={hd=x;tl=[]}indst.tl<-injr;looprtinletdummy=dummy_node()inloopdummyl;dummy.tlletrecfind_map_exnf=function|[]->raiseNot_found|x::xs->matchfxwith|Somey->y|None->find_map_exnfxsletrecfind_map_optf=function|[]->None|x::xs->matchfxwith|Some_asy->y|None->find_map_optfxsletfind_map=find_map_optletfilterifl=letrecfindnextidst=function|[]->()|h::t->iffihthenletr={hd=h;tl=[]}indst.tl<-injr;findnext(i+1)rtelsefindnext(i+1)dsttinletdummy=dummy_node()infindnext0dummyl;dummy.tlletfold_left_mapfaccul=letdummy=dummy_node()inletrecauxaccul_accu=function|[]->accu,dummy.tl|x::l->letaccu,x=faccuxinletr={hd=x;tl=[]}inl_accu.tl<-injr;auxaccurlinauxaccudummylletfold_right_max=1000letfold_rightflinit=letrectail_loopacc=function|[]->acc|h::t->tail_loop(fhacc)tinletrecloopn=function|[]->init|h::t->ifn<fold_right_maxthenfh(loop(n+1)t)elsefh(tail_loopinit(revt))inloop0lletmap2fl1l2=letrecloopdstsrc1src2=matchsrc1,src2with|[],[]->()|h1::t1,h2::t2->letr={hd=fh1h2;tl=[]}indst.tl<-injr;looprt1t2|_->raise(Different_list_size"map2")inletdummy=dummy_node()inloopdummyl1l2;dummy.tlletrev_map2fl1l2=letrecloopaccl1l2=matchl1,l2with|[],[]->acc|h1::t1,h2::t2->loop(fh1h2::acc)t1t2|_->raise(Different_list_size"rev_map2")inloop[]l1l2letreciter2fl1l2=matchl1,l2with|[],[]->()|h1::t1,h2::t2->fh1h2;iter2ft1t2|_->raise(Different_list_size"iter2")letrecfold_left2faccuml1l2=matchl1,l2with|[],[]->accum|h1::t1,h2::t2->fold_left2f(faccumh1h2)t1t2|_->raise(Different_list_size"fold_left2")letfold_right2fl1l2init=letrectail_loopaccl1l2=matchl1,l2with|[],[]->acc|h1::t1,h2::t2->tail_loop(fh1h2acc)t1t2|_->raise(Different_list_size"fold_right2")inletrecloopnl1l2=matchl1,l2with|[],[]->init|h1::t1,h2::t2->ifn<fold_right_maxthenfh1h2(loop(n+1)t1t2)elsefh1h2(tail_loopinit(revt1)(revt2))|_->raise(Different_list_size"fold_right2")inloop0l1l2letfor_all2pl1l2=letrecloopl1l2=matchl1,l2with|[],[]->true|h1::t1,h2::t2->ifph1h2thenloopt1t2elsefalse|_->raise(Different_list_size"for_all2")inloopl1l2letexists2pl1l2=letrecloopl1l2=matchl1,l2with|[],[]->false|h1::t1,h2::t2->ifph1h2thentrueelseloopt1t2|_->raise(Different_list_size"exists2")inloopl1l2letremove_assocxlst=letrecloopdst=function|[]->()|(a,_aspair)::t->ifa=xthendst.tl<-telseletr={hd=pair;tl=[]}indst.tl<-injr;looprtinletdummy=dummy_node()inloopdummylst;dummy.tlletremove_assqxlst=letrecloopdst=function|[]->()|(a,_aspair)::t->ifa==xthendst.tl<-telseletr={hd=pair;tl=[]}indst.tl<-injr;looprtinletdummy=dummy_node()inloopdummylst;dummy.tlletrfindpl=findp(revl)letfind_allpl=letrecfindnextdst=function|[]->()|h::t->ifphthenletr={hd=h;tl=[]}indst.tl<-injr;findnextrtelsefindnextdsttinletdummy=dummy_node()infindnextdummyl;dummy.tlletrecfindipl=letrecloopn=function|[]->raiseNot_found|h::t->ifpnhthen(n,h)elseloop(n+1)tinloop0lletfilter=find_allletpartitionplst=letrecloopyesdstnodst=function|[]->()|h::t->letr={hd=h;tl=[]}inifphthenbeginyesdst.tl<-injr;looprnodsttendelsebeginnodst.tl<-injr;loopyesdstrtendinletyesdummy=dummy_node()andnodummy=dummy_node()inloopyesdummynodummylst;yesdummy.tl,nodummy.tlletsplitlst=letrecloopadstbdst=function|[]->()|(a,b)::t->letx={hd=a;tl=[]}andy={hd=b;tl=[]}inadst.tl<-injx;bdst.tl<-injy;loopxytinletadummy=dummy_node()andbdummy=dummy_node()inloopadummybdummylst;adummy.tl,bdummy.tlletcombinel1l2=letrecloopdstl1l2=matchl1,l2with|[],[]->()|h1::t1,h2::t2->letr={hd=h1,h2;tl=[]}indst.tl<-injr;looprt1t2|_,_->raise(Different_list_size"combine")inletdummy=dummy_node()inloopdummyl1l2;dummy.tlletsort?(cmp=Stdlib.compare)=List.sortcmp#ifOCAML<406letrecinitsizef=ifsize=0then[]elseifsize<0theninvalid_arg"ExtList.init"elseletrecloopdstn=ifn<sizethenletr={hd=fn;tl=[]}indst.tl<-injr;loopr(n+1)inletr={hd=f0;tl=[]}inloopr1;injr#endifletmakeix=ifi<0theninvalid_arg"ExtList.List.make";letrecloopaccx=function|0->acc|i->loop(x::acc)x(i-1)inloop[]xiletmapif=function|[]->[]|h::t->letrecloopdstn=function|[]->()|h::t->letr={hd=fnh;tl=[]}indst.tl<-injr;loopr(n+1)tinletr={hd=f0h;tl=[]}inloopr1t;injrletfirst=hdletreclast=function|[]->raiseEmpty_list|h::[]->h|_::t->lasttletsplit_nthindex=function|[]->ifindex=0then[],[]elseraise(Invalid_indexindex)|(h::tasl)->ifindex=0then[],lelseifindex<0thenraise(Invalid_indexindex)elseletrecloopndstl=ifn=0thenlelsematchlwith|[]->raise(Invalid_indexindex)|h::t->letr={hd=h;tl=[]}indst.tl<-injr;loop(n-1)rtinletr={hd=h;tl=[]}ininjr,loop(index-1)rtletfind_excfel=tryfindflwithNot_found->raiseeletremovelx=letrecloopdst=function|[]->()|h::t->ifx=hthendst.tl<-telseletr={hd=h;tl=[]}indst.tl<-injr;looprtinletdummy=dummy_node()inloopdummyl;dummy.tlletrecremove_ifflst=letrecloopdst=function|[]->()|x::l->iffxthendst.tl<-lelseletr={hd=x;tl=[]}indst.tl<-injr;looprlinletdummy=dummy_node()inloopdummylst;dummy.tlletrecremove_alllx=letrecloopdst=function|[]->()|h::t->ifx=hthenloopdsttelseletr={hd=h;tl=[]}indst.tl<-injr;looprtinletdummy=dummy_node()inloopdummyl;dummy.tlletenuml=letrecmakelrcount=Enum.make~next:(fun()->match!lrwith|[]->raiseEnum.No_more_elements|h::t->decrcount;lr:=t;h)~count:(fun()->if!count<0thencount:=length!lr;!count)~clone:(fun()->make(ref!lr)(ref!count))inmake(refl)(ref(-1))letof_enume=leth=dummy_node()inlet_=Enum.fold(funxacc->letr={hd=x;tl=[]}inacc.tl<-injr;r)heinh.tl#ifOCAML<403letconsxl=x::l#endif#ifOCAML<405letassoc_optkl=trySome(assockl)withNot_found->Noneletassq_optkl=trySome(assqkl)withNot_found->Noneletfind_optpl=trySome(findpl)withNot_found->Noneletnth_opt=letrecloopn=function|[]->None|h::t->ifn=0thenSomehelseloop(n-1)tinfunlindex->ifindex<0thenNoneelseloopindexlletreccompare_lengthsl1l2=matchl1,l2with|[],[]->0|[],_->-1|_,[]->1|_::l1,_::l2->compare_lengthsl1l2letreccompare_length_withln=matchl,nwith|[],0->0|[],_->ifn>0then-1else1|_,0->1|_::l,n->compare_length_withl(n-1)#endif#ifOCAML<410letconcat_mapfl=letrecauxfacc=function|[]->revacc|x::l->letxs=fxinauxf(rev_appendxsacc)linauxf[]l#endif#ifOCAML<412letrecequaleql1l2=matchl1,l2with|[],[]->true|[],_::_|_::_,[]->false|a1::l1,a2::l2->eqa1a2&&equaleql1l2letreccomparecmpl1l2=matchl1,l2with|[],[]->0|[],_::_->-1|_::_,[]->1|a1::l1,a2::l2->letc=cmpa1a2inifc<>0thencelsecomparecmpl1l2#endifendlet(@)=List.append