
##############
### list.g ###
##############

#############################################################################
##
#F  List( <obj> ) . . . . . . . . . . . . . . . . . . . . . convert to a list
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="List",
    sin:=[[list,"l"],[func,"f"]],
    sou:=[],
    short:=
      "Apply `f' to every member of `l' and return the list of return values.",
    ex:=["l:=[1,2,3,4];\n"+
         "List(l,i->3*i);",
         "l:=[1,2,3,4];\n"+
         "List(l,IsEven);"],
    see:=[]), _Apply_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="List",
    sin:=[[func,"f"],[list,"l"]],
    sou:=[],
    short:=
      "Apply `f' to every member of `l' and return the list of return values.",
    ex:=["l:=[1,2,3,4];\n"+
         "List(i->3*i,l);",
         "l:=[1,2,3,4];\n"+
         "List(IsEven,l);"],
    see:=[]), _Apply_func_list);
#InstallMethod(
#  rec(
#    kind:="FUNCTION",
#    name:="List",
#    sin:=[[any,"l"]],
#    sou:=[[list]],
#    short:=
#      "Return the list constructed by the elements of `l'.\n"+
#      "Note: Use this construction to obtain a list from various "+
#      "types like seq, tup and the like.",
#    ex:=["List([1,2,3,4]);"],
#    see:=[]), _List_any);

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Size",
    sin:=[[string,"s"]],
    sou:=[[elt-ord^rat]],
    short:="Count the number of characters in `s'.",
    ex:=["Number(\"How many characters do I have?\");"],
    see:=[]), _Size_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Size",
    sin:=[[list,"l"]],
    sou:=[[elt-ord^rat]],
    short:="Count the number of list elements `l'.",
    ex:=["Size([1,2,4,3]);"],
    see:=[]), _Size_list);


#############################################################################
##
#F  Apply_( <list>, <func> ) . apply a function to list entries destructively
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Apply_",
    sin:=[[list,"l"],[func,"f"]],
    sou:=[],
    short:=
      "Apply 'f' to every member of `l' and replace the entry by "+
      "the corresponding return value.\n"+
      "Note: The previous contents of `l' will be lost.",
    ex:=["l:=[1,2,3,4];\n"+
         "Apply_(l,i->3*i); l;",
         "l:=[1,2,3,4];\n"+
         "Apply_(l,IsEven); l;"],
    see:=[]), _Apply__list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Apply_",
    sin:=[[func,"f"],[list,"l"]],
    sou:=[],
    short:=
      "Apply 'f' to every member of `l' and replace the entry by "+
      "the corresponding return value.\n"+
      "Note: The previous contents of `l' will be lost.",
    ex:=["l:=[1,2,3,4];\n"+
         "Apply_(i->3*i,l); l;",
         "l:=[1,2,3,4];\n"+
         "Apply_(IsEven,l); l;"],
    see:=[]), _Apply__func_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Apply",
    sin:=[[list,"l"],[func,"f"]],
    sou:=[[list,"r"]],
    short:=
      "Return the list where every member 'b' of 'l' is replaced by 'f' applied to 'b'.",
    ex:=["l:=[1,2,3,4];\n"+
         "Apply(l,i->3*i); l;",
         "l:=[1,2,3,4];\n"+
         "Apply(l,IsEven); l;"],
    see:=[]), _Apply_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Apply",
    sin:=[[func,"f"],[list,"A"]],
    sou:=[[list,"r"]],
    short:=
      "Apply 'f' to every member of `A' and replace the entry by "+
      "the corresponding return value.\n"+
      "Note: The previous contents of `l' will be lost.",
    ex:=["l:=[1,2,3,4];\n"+
         "Apply(i->3*i,l); l;",
         "l:=[1,2,3,4];\n"+
         "Apply(IsEven,l); l;"],
    see:=[]), _Apply_func_list);

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Apply",
    sin:=[[func,"f"],[alist,"A"]],
    sou:=[[alist,"r"]],
    short:=
      "Apply `f' to every member of `A' and return the alist of return values.",
    ex:=["l:=Alist([3,1],[6,2],[9,3],[12,4]);\n"+
         "Apply(i->3*i,l);",
         "l:=[1,2,3,4];\n"+
         "Apply(IsEven,l);"],
    see:=[]), _Apply_func_alist);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Apply",
    sin:=[[alist,"l"],[func,"f"]],
    sou:=[[alist,"r"]],
    short:=
      "Apply `f' to every member of `l' and return the alist of return values.",
    ex:=["l:=Alist([3,1],[6,2],[9,3],[12,4]);\n"+
         "Apply(l,i->3*i);",
         "l:=[1,2,3,4];\n"+
         "Apply(l,IsEven);"],
    see:=[]), _Apply_alist_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Apply_",
    sin:=[[alist,"A"],[func,"f"]],
    sou:=[],
    short:=
      "Apply 'f' to every member of `A' and replace the entry by "+
      "the corresponding return value.\n"+
      "Note: The previous contents of `A' will be lost.",
    ex:=["l:=[1,2,3,4];\n"+
         "Apply_(l,i->3*i); l;",
         "l:=[1,2,3,4];\n"+
         "Apply_(l,IsEven); l;"],
    see:=[]), _Apply__list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Apply_",
    sin:=[[func,"f"],[alist,"A"]],
    sou:=[],
    short:=
      "Apply 'f' to every member of `A' and replace the entry by "+
      "the corresponding return value.\n"+
      "Note: The previous contents of `l' will be lost.",
    ex:=["l:=[1,2,3,4];\n"+
         "Apply_(i->3*i,l); l;",
         "l:=[1,2,3,4];\n"+
         "Apply_(IsEven,l); l;"],
    see:=[]), _Apply__func_list);
##List:=Copy(Apply);


#############################################################################
##
#F  GetEntry( <record>, <string> )
#F  GetEntry( <list>, <elt-ord^rat> )
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="GetEntry",
    sin:=[[record,"r"],[string,"f"]],
    opt:=[__FAILUREDOC],
    sou:=[[any]],
    short:="Returns the element of `r' in the field `f' if it exists and "+
      "fails otherwise.",
    ex:=["A:=rec(ac:=1,ad:=INFTY);\n"+
         "GetEntry(A,\"ad\");\n"+
         "GetEntry(A,\"ab\");"],
    see:=[]), _GetEntry_rec_string,
    rec(DefaultValues:=__FAILUREREC));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="GetEntry",
    sin:=[[list,"l"],[elt-ord^rat,"pos"]],
    opt:=[__FAILUREDOC],
    sou:=[[any]],
    short:="Returns the element of `l' at position `pos' if it exists and "+
      "fails otherwise.",
    ex:=["A:=[2,3,5,7,11,13,17,19];\n"+
         "GetEntry(A,2);\n"+
         "GetEntry(A,44);"],
    see:=[]), _GetEntry_list_eor,
    rec(DefaultValues:=__FAILUREREC));



#############################################################################
##
#F  Position( <alist>, <elt-ord^rat> )
#F  Position( <dry>, <elt-ord^rat> )
##
InstallMethod(
  rec( 
    kind:= "FUNCTION",
    name:= "Position",
    sin := [[list,"L"],[any,"a"]],
    opt := [[elt-ord^rat,"Start",
             "Determines the position where the search is started.",rec(Default:=1)],
            __FAILUREDOC],
    sou := [[elt-ord^rat]],
    short := "Return the position of the first occurence of `a' in `L' "+
    "if `a in L' is true, and FAILURE otherwise.",
    ex := ["L:=[1,,3,4];\n"+
    "Position(L,3); Position(L,1,rec(Start:=2)); Position(L,\"foo\");"],
    see := []), _Position_list_any,
    rec(DefaultValues:=__FAILUREREC));
InstallMethod(
  rec( 
    kind:= "FUNCTION",
    name:= "Position",
    sin := [[string,"S"],[char,"c"]],
    opt := [[elt-ord^rat,"Start",
             "Determines the position where the search is started.",rec(Default:=1)],
            __FAILUREDOC],
    sou := [[elt-ord^rat]],
    short := "Return the position of the first occurence of `c' in `S' "+
    "if c is a character in the string `S', and FAILURE otherwise.",
    ex := ["S:=\"foobar\";\n"+
    "Position(S,'o'); Position(S,'f',rec(Start:=2)); Position(S,\"foo\");"],
    see := []), _Position_list_any,
    rec(DefaultValues:=__FAILUREREC));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Position",
    sin:=[[dry,"D"],[any,"a"]],
    opt:=[[elt-ord^rat,"Start",
             "Determines the position where the search is started.",rec(Default:=1)],
          __FAILUREDOC],
    sou:=[[elt-ord^rat]],
    short := "Return the position of the occurence of `a' in `D' "+
    "if `a in D' is true, and FAILURE otherwise.",
    ex := ["D:=Dry([1,12,4,3]);\n"+
    "Position(D,12); Position(D,1,rec(Start:=2)); Position(D,\"foo\");"],
    see := []), DryPosition,
    rec(DefaultValues:=__FAILUREREC));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Position",
    sin:=[[alist,"A"],[any,"a"]],
    opt:=[[elt-ord^rat,"Start",
             "Determines the position where the search is started.",rec(Default:=1)],
          __FAILUREDOC],
    sou:=[[elt-ord^rat]],
    short := "Return the position of the occurence of `a' in `A' "+
    "if `a in A' is true, and FAILURE otherwise.",
    ex := ["A:=Alist([1,12],[3,4]);\n"+
    "Position(A,3); Position(A,1,rec(Start:=2)); Position(A,\"foo\");"],
    see := []), _Position_alist_any,
    rec(DefaultValues:=__FAILUREREC));




#############################################################################
##
#F  Mapconcat(<func>, <list>, <sep>)  . . . . . . . . concatentation of lists
#F  Mapconcat(<func>, <list>) . . . . . . . . . . . . concatentation of lists
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Mapconcat",
    sin:=[[func,"f"],[list,"l"],[string,"sep"]],
    sou:=[[string,"s"]],
    short:="Apply `f' to every member of `l' to obtain a string. "+
      "Then concatenate all these strings intermixed with `sep' and "+
      "return the result.",
    ex:=["Stringify:=function(arg) return SPrint(arg[1]); end;\n"+
         "Mapconcat(Stringify,[E,1,\"test\"],\", \");"],
    see:=[DocGenHashByString("Mapconcat(func,list)")]), _Mapconcat_func_list_string);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Mapconcat",
    sin:=[[func,"f"],[list,"l"]],
    sou:=[[string,"s"]],
    short:="Apply `f' to every member of `l' to obtain a string. "+
      "Then concatenate all these strings intermixed with a space and "+
      "return the result.",
    ex:=["Stringify:=function(arg) return SPrint(arg[1]); end;\n"+
         "Mapconcat(Stringify,[E,1,\"test\"]);"],
    see:=[DocGenHashByString("Mapconcat(func,list,string)")]), _Mapconcat_func_list);



#############################################################################
##
#F  Filtered( <list>, <func> )  . . . . extract elements that have a property
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Filtered",
    sin:=[[func,"pred"],[list,"l"]],
    sou:=[[list,"filt"]],
    short:="Gather elements from `l' which suffice the predicate function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Filtered(IsPrime,[1..100]);"],
    see:=[]), _Filtered_func_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Filtered",
    sin:=[[list,"l"],[func,"pred"]],
    sou:=[[list,"filt"]],
    short:="Gather elements from `l' which suffice the predicate function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Filtered([1..100],IsPrime);"],
    see:=[]), _Filtered_list_func);


#############################################################################
##
#F  Butfirst( <list> ) (a.k.a. Rest)
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Butfirst",
    sin:=[[list,"l"]],
    sou:=[[list,"r"]],
    short:="Return the list `l' without its first element.",
    see:=[DocHash("Butfirst_(list)")]));
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Butfirst_",
    sin:=[[list,"l"]],
    sou:=[[list,"r"]],
    short:="Remove the first element from the list `l'.\n"+
      "Note: `l' is modified by side-effect.",
    see:=[DocHash("Butfirst(list)")]));

#############################################################################
##
#F  First( <list> )
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="First",
    sin:=[[list,"l"]],
    sou:=[[any,"f"]],
    short:="Return the first element of the list `l'.",
    see:=[DocHash("Last(list)")]), First);

#############################################################################
##
#F  Butlast( <list> )
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Butlast",
    sin:=[[list,"l"]],
    sou:=[[list,"r"]],
    short:="Return the list `l' without its last element.",
    see:=[DocHash("Butlast_(list)")]));
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Butlast_",
    sin:=[[list,"l"]],
    sou:=[[list,"r"]],
    short:="Remove the last element from the list `l'.\n"+
      "Note: `l' is modified by side-effect.",
    see:=[DocHash("Butlast(list)")]));

#############################################################################
##
#F  Last( <list> )
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Last",
    sin:=[[list,"l"]],
    sou:=[[any,"r"]],
    short:="Return the last element of the list `l'.",
    see:=[DocHash("First(list)")]), Last);


#############################################################################
##
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Mapc",
    sin:=[[func,"f"],[list,"l"]],
    sou:=[],
    short:="Apply 'f' on each element of 'l' _without_ modifying 'l'."));

#############################################################################
##
#F  RunHookWithArg( <list>, <any> )  . . . . . . . . 
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="RunHookWithArg",
    sin:=[[list,"hook"],[any,"arg"]],
    sou:=[],
    short:="Run each function of the list `hook' with `arg' as argument.\n"+
      "This is unlike Mapc which takes _one_ function which acts on a list "+
      "of arguments.",
    ex:=["RunHookWithArg([i->i*2, i->i*3, i->i*4],2);"]));


#############################################################################
##
#F  Concatenation( <list>, <list> ) . . . . . . . . . concatentation of lists
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Concatenation",
    sin:=[[list,"l1"],[list,"l2"]],
    sou:=[[list,"l"]],
    short:="Concatenate the lists `l1' and `l2' and return the result.",
    ex:=["Concatenation([1,2],[3,4]);"],
    see:=[]));

#############################################################################
##
#F  Flat( <list> )  . . . . . . . list of elements of a nested list structure
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Flat",
    sin:=[[list,"l"]],
    sou:=[[list,"f"]],
    short:="Flatten `l' by recursing into a nested list structure and "+
      "fetching all atomary (i.e. non-lists) elements and return the "+
      "result.",
    ex:=["l:=[[1],[2,3,4]];\n"+
         "Flat(l);"],
    see:=[]));

#############################################################################
##
#F  Reversed( <list> )  . . . . . . . . . . .  reverse the elements in a list
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Reversed",
    sin:=[[list,"l"]],
    sou:=[[list,"r"]],
    short:="Reverse `l' and return the result.",
    ex:=["l:=[1,2,3,4];\n"+
         "Reversed(l);"],
    see:=[]));


#############################################################################
##
#F  Filter( <func> ) . . . . . . . . .  extract elements that have a property
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Filter",
    sin:=[[func,"pred"]],
    sou:=[[func,"filt"]],
    short:="Construct a functional `filt(<list> l) -> <list>' "+
      "which gathers elements from `l' which suffice the predicate "+
      "function `pred' which has to have out-signature `-> elt-alg^boo'.",
    ex:=["f:=Filter(IsPrime);\n"+
         "f([1..100]);\n"],
    see:=[]));


#############################################################################
##
#F  Number( <list> [, <func>] ) . . . . . count elements that have a property
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Number",
    sin:=[[list,"l"],[func,"pred"]],
    sou:=[[elt-ord^rat]],
    short:="Return the number of elements from `l' which suffice the "+
      "predicate function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Number([1..100],IsPrime);"],
    see:=[]), _Number_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Number",
    sin:=[[func,"pred"],[list,"l"]],
    sou:=[[elt-ord^rat]],
    short:="Return the number of elements from `l' which suffice the "+
      "predicate function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Number(IsPrime,[1..100]);"],
    see:=[]), _Number_func_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Number",
    sin:=[[list,"l"]],
    sou:=[[elt-ord^rat]],
    short:="Count the number of elements in `l'.",
    ex:=["Number([101,102,103]);",
         "Number([1,2,3,,,,,,4]);"],
    see:=[]), _Number_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Number",
    sin:=[[func,"pred"]],
    sou:=[[func,"ctr"]],
    short:="Construct a functional `ctr(<list> l) -> elt-ord^rat' "+
      "which returns the number of elements from `l' which suffice "+
      "the predicate function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["f:=Number(IsPrime);\n"+
         "f([1..100]);"],
    see:=[]), _Number_func);

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Number",
    sin:=[[string,"s"],[func,"pred"]],
    sou:=[[elt-ord^rat]],
    short:="Return the number of characters from `s' which suffice the "+
      "predicate function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Number(\"some really random text\",i->i in \"aeiou\");"],
    see:=[]), _Number_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Number",
    sin:=[[func,"pred"],[string,"s"]],
    sou:=[[elt-ord^rat]],
    short:="Return the number of characters from `s' which suffice the "+
      "predicate function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Number(i->not i in \"aeiou\",\"hm, this is a demonstration text\");"],
    see:=[]), _Number_func_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Number",
    sin:=[[string,"s"]],
    sou:=[[elt-ord^rat]],
    short:="Count the number of characters in `s'.",
    ex:=["Number(\"How many characters do I have?\");"],
    see:=[]), _Size_list);

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Number",
    sin:=[[seq(),"s"],[func,"pred"]],
    sou:=[[elt-ord^rat]],
    short:="Return the number of elements from `s' which suffice the "+
      "predicate function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Number(Sequence([1..100]),IsPrime);"],
    see:=[]), _Number_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Number",
    sin:=[[func,"pred"],[seq(),"s"]],
    sou:=[[elt-ord^rat]],
    short:="Return the number of elements from `s' which suffice the "+
      "predicate function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Number(IsPrime,Sequence([1..100]));"],
    see:=[]), _Number_func_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Number",
    sin:=[[seq(),"s"]],
    sou:=[[elt-ord^rat]],
    short:="Count the number of elements in `s'.",
    ex:=["Number(Sequence([101,102,103]));"],
    see:=[]), _Number_list);



#############################################################################
##
#F  ForAll( <list>, <func> )  . .  test a property for all elements of a list
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="ForAll",
    sin:=[[list,"l"],[func,"pred"]],
    sou:=[[elt-alg^boo]],
    short:="Return true iff every member of `l' suffices the predicate "+
      "function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["ForAll([1..100],IsPrime);",
         "ForAll([2,4,6,8,100],IsEven);"],
    see:=[]), _ForAll_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="ForAll",
    sin:=[[func,"pred"],[list,"l"]],
    sou:=[[elt-alg^boo]],
    short:="Return true iff every member of `l' suffices the predicate "+
      "function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["ForAll(IsPrime,[1..100]);",
         "ForAll(IsEven,[2,4,6,8,100]);"],
    see:=[]), _ForAll_func_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="ForAll",
    sin:=[[func,"pred"]],
    sou:=[[func,"fa"]],
    short:="Construct a functional `fa(<list> l) -> elt-alg^boo' "+
      "which returns true iff every member of `l' suffices the predicate "+
      "function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["l:=[Random(10),Random(10)];\n"+
         "f:=ForAll(IsEven);\n"+
         "l; f(l);"],
    see:=[]), _ForAll_func);

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="ForAll",
    sin:=[[seq(),"s"],[func,"pred"]],
    sou:=[[elt-alg^boo]],
    short:="Return true iff every element of `s' suffices the predicate "+
      "function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["ForAll(Sequence([1..100]),IsPrime);",
         "ForAll(Sequence([2,4,6,8,100]),IsEven);"],
    see:=[DocHash("ForAll(list,func)")]), _ForAll_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="ForAll",
    sin:=[[func,"pred"],[seq(),"s"]],
    sou:=[[elt-alg^boo]],
    short:="Return true iff every element of `s' suffices the predicate "+
      "function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["ForAll(IsPrime,Sequence([1..100]));",
         "ForAll(IsEven,Sequence([2,4,6,8,100]));"],
    see:=[DocHash("ForAll(func,list)")]), _ForAll_func_list);


#############################################################################
##
#F  ForAny( <list>, <func> )  . . . test a property for any element of a list
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="ForAny",
    sin:=[[list,"l"],[func,"pred"]],
    sou:=[[elt-alg^boo]],
    short:="Return true iff every member of `l' suffices the predicate "+
      "function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["ForAny([1..100],IsPrime);",
         "ForAny([2,4,6,8,100],IsEven);"],
    see:=[]), _ForAny_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="ForAny",
    sin:=[[func,"pred"],[list,"l"]],
    sou:=[[elt-alg^boo]],
    short:="Return true iff every member of `l' suffices the predicate "+
      "function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["ForAny(IsPrime,[1..100]);",
         "ForAny(IsOdd,[2,4,6,8,100]);"],
    see:=[]), _ForAny_func_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="ForAny",
    sin:=[[func,"pred"]],
    sou:=[[func,"fa"]],
    short:="Construct a functional `fa(<list> l) -> elt-alg^boo' "+
      "which returns true iff every member of `l' suffices the predicate "+
      "function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["l:=[Random(1000)..1000+Random(1000)];\n"+
         "f:=ForAny(IsPrime);\n"+
         "l; f(l);"],
    see:=[]), _ForAny_func);

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="ForAny",
    sin:=[[seq(),"s"],[func,"pred"]],
    sou:=[[elt-alg^boo]],
    short:="Return true iff every element of `s' suffices the predicate "+
      "function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["ForAny(Sequence([1..100]),IsPrime);",
         "ForAny(Sequence([2,4,6,8,100]),IsEven);"],
    see:=[DocHash("ForAny(list,func)")]), _ForAny_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="ForAny",
    sin:=[[func,"pred"],[seq(),"s"]],
    sou:=[[elt-alg^boo]],
    short:="Return true iff every element of `s' suffices the predicate "+
      "function `pred'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["ForAny(IsPrime,Sequence([1..100]));",
         "ForAny(IsOdd,Sequence([2,4,6,8,100]));"],
    see:=[DocHash("ForAny(func,list)")]), _ForAny_func_list);


#############################################################################
##
#F  First( <list>, <func> ) . .  find first element in a list with a property
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="First",
    sin:=[[list,"l"],[func,"pred"]],
    opt:=[__FAILUREDOC],
    sou:=[[any]],
    short:="Find the first element which suffices the predicate function `pred' "+
      "and return it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["First([1..100],IsPrime);",
         "First([2,4,6,8,12,50,100],i->i mod 5=0);"],
    see:=[DocHash("Last(list,func)")]), _First_list_func,
    rec(DefaultValues:=__FAILUREREC));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="First",
    sin:=[[func,"pred"],[list,"l"]],
    opt:=[__FAILUREDOC],
    sou:=[[any]],
    short:="Find the first element which suffices the predicate function `pred' "+
      "and return it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["First(IsPrime,[1..100]);",
         "First(IsOdd,[2,4,6,8,100]);"],
    see:=[DocHash("Last(func,list)")]), _First_func_list,
    rec(DefaultValues:=__FAILUREREC));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="First",
    sin:=[[func,"pred"]],
    opt:=[__FAILUREDOC],
    sou:=[[func,"fir"]],
    short:="Construct a functional `fir(<list> l) -> any' "+
      "which finds and returns the first element which suffices the predicate "+
      "function `pred' and returns it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["l:=[Random(1000)..1000+Random(1000)];\n"+
         "f:=First(i->i mod 17=0);\n"+
         "l; f(l);"],
    see:=[DocHash("Last(func)")]), _First_func,
    rec(DefaultValues:=__FAILUREREC));

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="First",
    sin:=[[string,"s"],[func,"pred"]],
    opt:=[__FAILUREDOC],
    sou:=[[char]],
    short:="Find the first character which suffices the predicate function `pred' "+
      "and return it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["First(\"abcdefzyx\",i->(i='d' or i='z'));"],
    see:=[DocHash("Last(string,func)")]), _First_list_func,
    rec(DefaultValues:=__FAILUREREC));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="First",
    sin:=[[func,"pred"],[string,"s"]],
    opt:=[__FAILUREDOC],
    sou:=[[char]],
    short:="Find the first character which suffices the predicate function `pred' "+
      "and return it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["First(i->(i='d' or i='z'),\"abcdefzyx\");"],
    see:=[DocHash("Last(func,string)")]), _First_func_list,
    rec(DefaultValues:=__FAILUREREC));

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="First",
    sin:=[[seq(),"s"],[func,"pred"]],
    opt:=[__FAILUREDOC],
    sou:=[[any]],
    short:="Find the first element which suffices the predicate function `pred' "+
      "and return it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["First(Sequence([1..100]),IsPrime);",
         "First(Sequence([2,4,6,8,12,50,100]),i->i mod 5=0);"],
    see:=[DocHash("Last(seq(),func)")]), _First_list_func,
    rec(DefaultValues:=__FAILUREREC));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="First",
    sin:=[[func,"pred"],[seq(),"s"]],
    opt:=[__FAILUREDOC],
    sou:=[[any]],
    short:="Find the first element which suffices the predicate function `pred' "+
      "and return it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["First(IsPrime,Sequence([1..100]));",
         "First(IsOdd,Sequence([2,4,6,8,100]));"],
    see:=[DocHash("Last(func,list)")]), _First_func_list,
    rec(DefaultValues:=__FAILUREREC));


#############################################################################
##
#F  Last( <list>, <func> ) . . .  find last element in a list with a property
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Last",
    sin:=[[list,"l"],[func,"pred"]],
    opt:=[__FAILUREDOC],
    sou:=[[any]],
    short:="Find the last element which suffices the predicate function `pred' "+
      "and return it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Last([1..100],IsPrime);",
         "Last([2,4,6,8,12,50,100],i->i mod 3=0);"],
    see:=[DocHash("First(list,func)")]), _Last_list_func,
    rec(DefaultValues:=__FAILUREREC));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Last",
    sin:=[[func,"pred"],[list,"l"]],
    opt:=[__FAILUREDOC],
    sou:=[[any]],
    short:="Find the last element which suffices the predicate function `pred' "+
      "and return it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Last(IsPrime,[1..100]);",
         "Last(IsOdd,[2,4,6,8,100]);"],
    see:=[DocHash("First(func,list)")]), _Last_func_list,
    rec(DefaultValues:=__FAILUREREC));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Last",
    sin:=[[func,"pred"]],
    opt:=[__FAILUREDOC],
    sou:=[[func,"las"]],
    short:="Construct a functional `las(<list> l) -> any' "+
      "which finds and returns the last element which suffices the predicate "+
      "function `pred' and returns it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["l:=[Random(1000)..1000+Random(1000)];\n"+
         "f:=Last(i->i mod 17=0);\n"+
         "l; f(l);"],
    see:=[DocHash("First(func)")]), _Last_func,
    rec(DefaultValues:=__FAILUREREC));

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Last",
    sin:=[[string,"s"],[func,"pred"]],
    opt:=[__FAILUREDOC],
    sou:=[[char]],
    short:="Find the last character which suffices the predicate function `pred' "+
      "and return it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Last(\"test\",i->i<'s');"],
    see:=[DocHash("First(string,func)")]), _Last_list_func,
    rec(DefaultValues:=__FAILUREREC));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Last",
    sin:=[[func,"pred"],[string,"s"]],
    opt:=[__FAILUREDOC],
    sou:=[[char]],
    short:="Find the last character which suffices the predicate function `pred' "+
      "and return it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Last(i->i>'f',\"this is a demo.\");"],
    see:=[DocHash("First(func,string)")]), _Last_func_list,
    rec(DefaultValues:=__FAILUREREC));

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Last",
    sin:=[[seq(),"s"],[func,"pred"]],
    opt:=[__FAILUREDOC],
    sou:=[[any]],
    short:="Find the last element which suffices the predicate function `pred' "+
      "and return it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Last(Sequence([1..100]),IsPrime);",
         "Last(Sequence([2,4,6,8,12,50,100]),i->i mod 3=0);"],
    see:=[DocHash("First(seq(),func)")]), _Last_list_func,
    rec(DefaultValues:=__FAILUREREC));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Last",
    sin:=[[func,"pred"],[seq(),"s"]],
    opt:=[__FAILUREDOC],
    sou:=[[any]],
    short:="Find the last element which suffices the predicate function `pred' "+
      "and return it.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["Last(IsPrime,Sequence([1..100]));",
         "Last(IsOdd,Sequence([2,4,6,8,100]));"],
    see:=[DocHash("First(func,seq())")]), _Last_func_list,
    rec(DefaultValues:=__FAILUREREC));


#############################################################################
##
#F  PositionProperty( <list>, <func> ) position of an element with a property
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="PositionProperty",
    sin:=[[list,"l"],[func,"pred"]],
    opt:=[__FAILUREDOC],
    sou:=[[elt-ord^rat]],
    short:="Return the position of the first element of `l' which suffices "+
      "the predicate function `pred'.\n"+
      "Return FAILURE if no such element exists in `l'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["PositionProperty([50..100],IsPrime);",
         "PositionProperty([2,4,6,8,12,50,100],i->i mod 5=0);"],
    see:=[]), _PositionProperty_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="PositionProperty",
    sin:=[[func,"pred"],[list,"l"]],
    opt:=[__FAILUREDOC],
    sou:=[[elt-ord^rat]],
    short:="Return the position of the first element of `l' which suffices "+
      "the predicate function `pred'.\n"+
      "Return FAILURE if no such element exists in `l'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["PositionProperty(IsPrime,[1..100]);",
         "PositionProperty(IsOdd,[2,4,6,8,100]);"],
    see:=[]), _PositionProperty_func_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="PositionProperty",
    sin:=[[func,"pred"]],
    opt:=[__FAILUREDOC],
    sou:=[[func,"pos"]],
    short:="Construct a functional `pos(<list> l) -> elt-ord^rat' "+
      "which returns the position of the first element of `l' which suffices "+
      "the predicate function `pred'.\n"+
      "Return FAILURE if no such element exists in `l'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["l:=[Random(1000)..1000+Random(1000)];;\n"+
         "f:=PositionProperty(i->i mod 17=0);;\n"+
         "l; f(l);"],
    see:=[]), _PositionProperty_func);

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="PositionProperty",
    sin:=[[string,"s"],[func,"pred"]],
    opt:=[__FAILUREDOC],
    sou:=[[elt-ord^rat]],
    short:="Return the position of the first character of `s' which suffices "+
      "the predicate function `pred'.\n"+
      "Return FAILURE if no such character exists in `s'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["PositionProperty(\"some random text\",i->i in \"uvwxyz\");"],
    see:=[]), _PositionProperty_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="PositionProperty",
    sin:=[[func,"pred"],[string,"s"]],
    opt:=[__FAILUREDOC],
    sou:=[[elt-ord^rat]],
    short:="Return the position of the first character of `s' which suffices "+
      "the predicate function `pred'.\n"+
      "Return FAILURE if no such character exists in `s'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["PositionProperty(i->i in \"aeiou\",\"some random text\");"],
    see:=[]), _PositionProperty_func_list);

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="PositionProperty",
    sin:=[[seq(),"s"],[func,"pred"]],
    opt:=[__FAILUREDOC],
    sou:=[[elt-ord^rat]],
    short:="Return the position of the first element of `s' which suffices "+
      "the predicate function `pred'.\n"+
      "Return FAILURE if no such element exists in `s'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["PositionProperty(Sequence([50..100]),IsPrime);",
         "PositionProperty(Sequence([2,4,6,8,12,50,100]),i->i mod 5=0);"],
    see:=[DocHash("PositionProperty(list,func)")]), _PositionProperty_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="PositionProperty",
    sin:=[[func,"pred"],[seq(),"s"]],
    opt:=[__FAILUREDOC],
    sou:=[[elt-ord^rat]],
    short:="Return the position of the first element of `s' which suffices "+
      "the predicate function `pred'.\n"+
      "Return FAILURE if no such element exists in `s'.\n"+
      "Note: Apparently `pred' must have `-> elt-alg^boo' out-signature.",
    ex:=["PositionProperty(IsPrime,Sequence([1..100]));",
         "PositionProperty(IsOdd,Sequence([2,4,6,8,100]));"],
    see:=[DocHash("PositionProperty(func,list)")]), _PositionProperty_func_list);



#############################################################################
##
#F  Collected( <list> ) . . . . .
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Collected",
    sin:=[[list,"l"]],
    sou:=[[list,"coll"]],
    short:="Document me!",
    ex:=["Collected([1,2,3,3,2,5,4,3,2,1,4,4,3]);"],
    see:=[]));


#############################################################################
##
#F  Equivalenceclasses( <list>, <function> )  . calculate equivalence classes
#C  Completely obscure function, do not use me!
##
##  returns
##
##      rec(
##          classes := <list>,
##          indices := <list>
##      )
##
#InstallDocumentation(
#  rec(
#    kind:="FUNCTION",
#    name:="Equivalenceclasses",
#    sin:=[[list,"l"],[func,"equi"]],
#    sou:=[[record]],
#    short:="Document me!",
#    ex:=["f:=function(i,j) return i-j=2 or j-i=2; end;\n"+
#         "Equivalenceclasses([1..100],f); WTF?"],
#    see:=[]));


#############################################################################
##
#F  Cartesian( <list>, <list>.. ) . . . . . . . .  cartesian product of lists
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Cartesian",
    sin:=[[list,"l1"],[list,"l2"]],
    sou:=[[list,"l1xl2"]],
    short:="Return list obtained by the cartesian product of `l1' and `l2'.",
    ex:=["Cartesian([1,2,3,4],[1,I]);"],
    see:=[]));


#############################################################################
##
#F  Sort( <list> )  . . . . . . . . . . . . . . . . . . . . . . . sort a list
##
##  Sort() uses Shell's diminishing increment sort, which extends bubblesort.
##  The bubble sort works by  running  through  the  list  again  and  again,
##  each time exchanging pairs of adjacent elements which are out  of  order.
##  Thus large elements "bubble" to the top, hence the name  of  the  method.
##  However elements need many moves to come close to their  final  position.
##  In shellsort the first passes do not compare element j with its  neighbor
##  but with the element j+h, where h is larger than one.  Thus elements that
##  aren't at their final position make large moves towards the  destination.
##  This increment h is diminished, until during the last  pass  it  is  one.
##  A good sequence of incremements is given by Knuth:  (3^k-1)/2,... 13,4,1.
##  For this sequence shellsort uses on average  approximatly  N^1.25  moves.
##
##  Shellsort is the method of choice to  sort  lists  for  various  reasons:
##  Shellsort is quite easy to get right, much easier than,  say,  quicksort.
##  It runs as fast as quicksort for lists with  less  than  ~5000  elements.
##  It handles both  almost  sorted  and  reverse  sorted  lists  very  good.
##  It works well  in  the  presence  of  duplicate  elements  in  the  list.
##  Says Sedgewick: "In short, if you have a sorting problem,  use the  above
##  program, then determine whether the extra effort required to  replace  it
##  with a sophisticated method will be worthwile."
##
##  Donald Knuth, The Art of Computer Programming, Vol.3, AddWes 1973, 84-95
##  Donald Shell, CACM 2, July 1959, 30-32
##  Robert Sedgewick, Algorithms 2nd ed., AddWes 1988, 107-123
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Sort",
    sin:=[[list,"l"]],
    sou:=[],
    short:="Sort `l'.",
    ex:=["A:=[1,14,3,7,2,1];\n"+
         "Sort(A); A;"],
    see:=[]));


#############################################################################
##
#F  SortParallel(<list>,<list2>)  . . . . . . . .  sort two lists in parallel
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="SortParallel",
    sin:=[[list,"l1"],[list,"l2"]],
    sou:=[],
    short:="Document me!",
    ex:=[],
    see:=[]));


#############################################################################
##
#F  Permuted( <list>, <perm> )  . . . apply permutation <perm> to list <list>
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Permuted",
    sin:=[[list,"l"],[elt-grp^per,"perm"]],
    sou:=[],
    short:="Document me!",
    ex:=[],
    see:=[]));



#############################################################################
##
#F  PositionSorted( <list>, <elm> ) . . . .  find an element in a sorted list
##
##  'PositionSorted' uses a binary search instead of the linear  search  used
##  'Position'.  This takes log to base 2 of  'Size( <list> )' comparisons.
##  The list <list> must be  sorted  however  for  'PositionSorted'  to work.
##
##  Jon Bentley, Programming Pearls, AddWes 1986, 85-88
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="PositionSorted",
    sin:=[[list,"l"],[any,"elm"]],
    sou:=[[elt-ord^rat]],
    short:="Returns the position of `elm' in the sorted list `l'.",
    ex:=["A:=[2,3,5,7,11,13,17,19];\n"+
         "PositionSorted(A,11);"],
    see:=[]));



#############################################################################
##
#F  Product( <list> ) . . . . . . . . . . . product of the elements in a list
##
##  'Product( <list> )' \\
##  'Product( <list>, <func> )'
##
##  When used in the first way 'Product' returns the product of the  elements
##  of the list <list>.  When used in the second way  'Product'  applies  the
##  function <func>, which must  be  a  function  taking  one  argument,  and
##  returns the product of the results.  In either case if  <list>  is  empty
##  'Product' returns 1.
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Product",
    sin:=[[list,"l"]],
    sou:=[[any]],
    short:="Return the product of the elements of `l'.\n"+
      "Note: `l' may consist of elements of different types. "+
      "Generally `Product' works on everything `*' can operate on.",
    ex:=["Product([2,3,5,7]);",
         "Product([2,\"1,2 \",2]);"],
    see:=[]), _Product_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Product",
    sin:=[[seq(),"s"]],
    sou:=[[any]],
    short:="Return the product of the elements of `s'.",
    ex:=["Product(Sequence([2,3,5,7]));"],
    see:=[DocHash("Product(list)")]), _Product_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Product",
    sin:=[[tup(),"t"]],
    sou:=[[any]],
    short:="Return the product of the elements of `t'.",
    ex:=["Product(Tuple([2,3,5,7]));",
         "Product(Tuple([2,\"a,b \",5]));"],
    see:=[DocHash("Product(list)")]), _Product_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Product",
    sin:=[[list,"l"],[func,"f"]],
    sou:=[[any]],
    short:="Document me!",
    ex:=[],
    see:=[]), _Product_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Product",
    sin:=[[func,"l"],[list,"l"]],
    sou:=[[any]],
    short:="Document me!",
    ex:=[],
    see:=[]), _Product_func_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Product",
    sin:=[[func,"l"]],
    sou:=[[any]],
    short:="Document me!",
    ex:=[],
    see:=[]), _Product_func);


#############################################################################
##
#F  Sum( <list> ) . . . . . . . . . . . . . . . sum of the elements of a list
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Sum",
    sin:=[[list,"l"]],
    sou:=[[any]],
    short:="Return the sum of the elements of `l'.\n"+
      "Note: `l' may consist of elements of different types. "+
      "Generally `Sum' works on everything `+' can operate on.",
    ex:=["Sum([1..100]);",
         "Sum([\"a\",\"b\",\"c\"]);"],
    see:=[]), _Sum_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Sum",
    sin:=[[seq(),"s"]],
    sou:=[[any]],
    short:="Return the sum of the elements of `s'.",
    ex:=["Sum(Sequence([1..100]));",
         "Sum(Sequence([\"a\",\"b\",\"c\"]));"],
    see:=[]), _Sum_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Sum",
    sin:=[[tup(),"t"]],
    sou:=[[any]],
    short:="Return the sum of the elements of `t'.",
    ex:=["Sum(Tuple([1..100]));",
         "Sum(Tuple([\"a\",\"b\",\"c\"]));"],
    see:=[]), _Sum_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Sum",
    sin:=[[list,"l"],[func,"f"]],
    sou:=[[any]],
    short:="Document me!",
    ex:=[],
    see:=[]), _Sum_list_func);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Sum",
    sin:=[[func,"f"],[list,"l"]],
    sou:=[[any]],
    short:="Document me!",
    ex:=[],
    see:=[]), _Sum_func_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Sum",
    sin:=[[func,"f"]],
    sou:=[[any]],
    short:="Document me!",
    ex:=[],
    see:=[]), _Sum_func);


#############################################################################
##
#F  Iterated( <list>, <func> )  . . . . . . .  iterate a function over a list
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Iterated",
    sin:=[[list,"l"],[func,"f"]],
    sou:=[[any]],
    short:="Document me!",
    ex:=[],
    see:=[]));


#############################################################################
##
#F  Maximum( <obj>, <obj>... )  . . . . . . . . . . . . . maximum of integers
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Maximum",
    sin:=[[set,"s"]],
    sou:=[[any]],
    short:="Determine and return the maximal element of `s'.\n"+
      "Note: `s' may also be a list (nonetheless `Set(s)' must exist).",
    ex:=["Maximum([3,-3,5]);",
         "Maximum(['a','b']);"],
    see:=[]));
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Maximum",
    sin:=[[seq(),"l"]],
    sou:=[[any]],
    short:="Determine and return the maximal element of `s'.",
    ex:=["Maximum(Sequence([3,-3,5]));",
         "Maximum(Sequence(['a','b']));"],
    see:=[]));
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Maximum",
    sin:=[[tup(),"l"]],
    sou:=[[any]],
    short:="Determine and return the maximal element in `t'.",
    ex:=["Maximum(Tuple([3,-3,5]));",
         "Maximum(Tuple(['a','b']));"],
    see:=[]));


#############################################################################
##
#F  Minimum( <obj>, <obj>... )  . . . . . . . . . . . . . minimum of integers
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Minimum",
    sin:=[[set,"s"]],
    sou:=[[any]],
    short:="Determine and return the minimal element of `s'.\n"+
      "Note: `s' may also be a list (nonetheless `Set(s)' must exist).",
    ex:=["Minimum([3,-3,5]);",
         "Minimum(['a','b']);"],
    see:=[]));
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Minimum",
    sin:=[[seq(),"l"]],
    sou:=[[any]],
    short:="Determine and return the minimal element of `s'.",
    ex:=["Minimum(Sequence([3,-3,5]));",
         "Minimum(Sequence(['a','b']));"],
    see:=[]));
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Minimum",
    sin:=[[tup(),"l"]],
    sou:=[[any]],
    short:="Determine and return the minimal element in `t'.",
    ex:=["Minimum(Tuple([3,-3,5]));",
         "Minimum(Tuple(['a','b']));"],
    see:=[]));


#############################################################################
##
#F  Remove( <list> )
#F  Remove( <seq> )
##
InstallMethod(
  rec( 
    kind:= "FUNCTION",
    name:= "Remove",
    sin := [[list,"L"],[elt-ord^rat,"pos"]],
    opt := [__FAILUREDOC],
    sou := [[list]],
    short := "Return the list derived from removing the element at position "+
    "`pos' from `L'.\n"+
    "Note: `pos' must not exceed the scope of `L'.\n"+
    "Note: This function returns the list created by the removal but does "+
    "not affect `L'.",
    ex := ["L:=[1,,3,4];\n"+
    "Remove(L,3); L;"],
    see := [DocHash("Remove_(list,elt-ord^rat)")]
    ), _Remove_list_eor);
InstallMethod(
  rec( 
    kind:= "FUNCTION",
    name:= "Remove_",
    sin := [[list,"L"],[elt-ord^rat,"pos"]],
    opt := [__FAILUREDOC,
            __SUCCESSDOC],
    sou := [],
    short := "Remove the element at position `pos' in the list `L'.\n"+
    "Note: `pos' must not exceed the scope of `L'.\n"+
    "Note: This function works by side effect and returns VOID.",
    ex := ["L:=[1,,3,4];\n"+
    "Remove_(L,3); L;"],
    see := [DocHash("Remove(list,elt-ord^rat)")]
    ), _Remove__list_eor);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Remove",
    sin:=[[seq(),"S"],[elt-ord^rat,"pos"]],
    sou:=[[seq()]],
    short := "Return the sequence derived from removing the element at position "+
    "`pos' from `S'.\n"+
    "Note: `pos' must not exceed the scope of `S'.\n"+
    "Note: This function returns the sequence created by the removal but does "+
    "not affect `S'."), _Remove_list_eor);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Remove_",
    sin:=[[seq(),"S"],[elt-ord^rat,"pos"]],
    sou:=[[]],
    short := "Remove the element at position `pos' in the sequence `S'.\n"+
    "Note: `pos' must not exceed the scope of `S'.\n"+
    "Note: This function works by side effect and returns VOID."), _Remove__list_eor);


#############################################################################
##
#F  Add( <list> )
#F  Add( <seq> )
#F  Add( <tup> )
##
InstallMethod(
  rec( 
    kind:= "FUNCTION",
    name:= "Add_",
    sin := [[list,"L"],[any,"a"]],
    sou := [],
    short := "Add `a' to `L' by assigning `a' at the next position beyond the "+
    "scope of `L'.\n"+
    "Note: This function works by side effect and returns VOID.",
    ex := ["L:=[1,,3,4];\nAdd_(L,5); L;"],
    see := [DocHash("Add(list,any)"),
            DocHash("Append(list,list)")]), _Add__list_any);
InstallMethod(
  rec( 
    kind:= "FUNCTION",
    name:= "Add",
    sin := [[list,"L"],[any,"a"]],
    sou := [[list]],
    short := "Add `a' to `L' by assigning `a' at the next position beyond the "+
    "scope of `L'.\n"+
    "Note: This function returns the list created by the addition but does "+
    "not affect `L'.",
    ex := ["L:=[1,,3,4];\nAdd(L,5); L;"],
    see := [DocHash("Add_(list,any)"),
            DocHash("Append_(list,list)")]), _Add_list_any);

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Add",
    sin:=[[seq(),"Q"],[any,"x"]],
    sou:=[[seq()]],
    short:="The sequence built by appending x to the sequence Q.",
    ex:=["L:=Sequence([1,2,3,4]);\nAdd(L,5); L;"],
    see:=[DocHash("Add(list,any)"),
          DocHash("Append(seq(),seq())")]), _Add_list_any);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Add_",
    sin:=[[seq(),"Q"],[any,"x"]],
    sou:=[[seq()]],
    short:="Modify `Q' by appending x to the sequence Q.",
    ex:=["L:=Sequence([1,2,3,4]);\nAdd_(L,5); L;"],
    see:=[DocHash("Add_(list,any)"),
          DocHash("Append_(seq(),seq())")]), _Add__list_any);

InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Add",
    sin:=[[string,"S"],[char,"c"]],
    sou:=[[string]],
    short:="The string built by appending `c' to the string `S'.\n"+
      "Note: This is roughly equivalent to `S+c'.",
    ex:=["S:=\"abcdef\";\nAdd(S,'z'); S;"],
    see:=[DocHash("Add(list,any)"),
          DocHash("Append(string,string)")]), _Add_list_any);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Add_",
    sin:=[[string,"S"],[char,"c"]],
    sou:=[[string]],
    short:="Modify `S' by appending `c' to the string `S'.",
    ex:=["S:=\"abcdef\";\nAdd_(S,'z'); S;"],
    see:=[DocHash("Add_(list,any)"),
          DocHash("Append_(string,string)")]), _Add__list_any);



###################
### set.c/dry.c ###
###################

#############################################################################
##
#F  Union( <dry> )
#F  Union( <set> )
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Union",
    sin:=[[dry,"D1"],[list,"D2"]],
    sou:=[[dry]],
    short:="Return the dry derived by the union of `D1' and `D2'.\n"+
      "The union is the dry of those elements that are elements of either dry. "+
      "So `"+~.name+"' adds (see DryAdd) all elements to `D1' that are in `D2'. "+
      "`D2' may be a list that is not a proper dry, in which case `Dry' is "+
      "silently applied to it.",
    ex:=[],
    see:=[]), DryUnion);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Union",
    sin:=[[set,"S1"],[list,"S2"]],
    sou:=[[set]],
    short:="Return the set derived by the union of `S1' and `S2'.\n"+
      "The union is the dry of those elements that are elements of either dry. "+
      "So `"+~.name+"' adds (see SetAdd) all elements to `S1' that are in `S2'. "+
      "`S2' may be a list that is not a proper set, in which case `Set' is "+
      "silently applied to it.",
    ex:=[],
    see:=[]), SetUnion);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Union_",
    sin:=[[dry,"D1"],[list,"D2"]],
    sou:=[],
    short:="Change `D1' so that it becomes the union of `D1' and `D2'.\n"+
      "The union is the dry of those elements that are elements of either dry. "+
      "So `"+~.name+"' adds (see DryAdd) all elements to `D1' that are in `D2'. "+
      "`D2' may be a list that is not a proper dry, in which case `Dry' is "+
      "silently applied to it.",
    ex:=[],
    see:=[]), DryUnion_);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Union_",
    sin:=[[set,"S1"],[list,"S2"]],
    sou:=[],
    short:="Change `S1' so that it becomes the union of `S1' and `S2'.\n"+
      "The union is the dry of those elements that are elements of either dry. "+
      "So `"+~.name+"' adds (see SetAdd) all elements to `S1' that are in `S2'. "+
      "`S2' may be a list that is not a proper set, in which case `Set' is "+
      "silently applied to it.",
    ex:=[],
    see:=[]), SetUnion_);

#############################################################################
##
#F  Intersection( <dry> )
#F  Intersection( <set> )
##
InstallMethod(
  rec(
  kind := "FUNCTION",
  name := "Intersection",
  sin  := [[dry,"D1"],[list,"D2"]],
  sou  := [[dry]],
  short := "Return the dry derived by the intersection of the dries `D1' "+
    "and `D2'.\n"+
    "The intersection is the dry of those elements that are elements in "+
    "both dries. So `"+~.name+"' removes (see `DryRemove') all elements "+
    "from `D1' that are not in `D2'.\n"+
    "Note: `D2' may be a list that is not a proper dry, in which case `Dry' "+
    "is silently applied to it."
  ), DryIntersection);
InstallMethod(
  rec(
  kind := "FUNCTION",
  name := "Intersection",
  sin  := [[set,"S1"],[list,"S2"]],
  sou  := [[set]],
  short := "Return the set derived by the intersection of the sets `S1' "+
    "and `S2'.\n"+
    "The intersection is the set of those elements that are elements in "+
    "both sets. So `"+~.name+"' removes (see `SetRemove') all elements "+
    "from `S1' that are not in `S2'.\n"+
    "`S2' may be a list that is not a proper set, in which case `Set' "+
    "is silently applied to it."
  ), SetIntersection);
InstallMethod(
  rec(
  kind := "FUNCTION",
  name := "Intersection_",
  sin  := [[dry,"D1"],[list,"D2"]],
  sou  := [],
  short := "Change `D1' so that it becomes the intersection of `D1' and `D2'.\n"+
    "The intersection is the dry of those elements that are elements in "+
    "both dries. So `"+~.name+"' removes (see `DryRemove_') all elements "+
    "from `D1' which are not in `D2'.\n"+
    "Note: `D2' may be a list that is not a proper dry, in which case `Dry' "+
    "is silently applied to it."
  ), DryIntersection_);
InstallMethod(
  rec(
  kind := "FUNCTION",
  name := "Intersection_",
  sin  := [[set,"S1"],[list,"S2"]],
  sou  := [],
  short := "Change `S1' so that it becomes the intersection of `S1' "+
    "and `S2'.\n"+
    "The intersection is the set of those elements that are elements in "+
    "both sets. So `SetIntersection_' removes (see `SetRemove_') all elements "+
    "from `S1' that are not in `S2'.\n"+
    "`S2' may be a list that is not a proper set, in which case `Set' "+
    "is silently applied to it."
  ), SetIntersection_);


#############################################################################
##
#F  Difference( <dry> )
#F  Difference( <set> )
##
InstallMethod(
  rec(
  kind := "FUNCTION",
  name := "Difference",
  sin  := [[dry,"D1"],[list,"D2"]],
  sou  := [[dry]],
  short := "Return the dry derived by the difference of the dries `D1' "+
    "and `D2'.\n"+
    "The difference is the dry of the elements that are in `D1' but not "+
    "in `D2'. So `"+~.name+"' removes (see `DryRemove') all elements from "+
    "`D1' that are in `D2'.\n"+
    "Note: `D2' may be a list that is not a proper dry, in which case `Dry' "+
    "is silently applied to it."
  ), DryDifference);
InstallMethod(
  rec(
  kind := "FUNCTION",
  name := "Difference",
  sin  := [[set,"S1"],[list,"S2"]],
  sou  := [[set]],
  short := "Return the set derived by the difference of the sets `S1' "+
    "and `S2'.\n"+
    "The difference is the set of the elements that are in `S1' but not "+
    "in `S2'. So `"+~.name+"' removes (see `SetRemove') all elements from "+
    "`S1' that are in `S2'.\n"+
    "Note: `S2' may  be a list that is not a proper set, in which case `Set' "+
    "is silently applied to it."
  ), SetDifference);
InstallMethod(
  rec(
  kind := "FUNCTION",
  name := "Difference_",
  sin  := [[dry,"D1"],[list,"D2"]],
  sou  := [],
  short := "Change `D1' so that it becomes the difference of `D1' and `D2'.\n"+
    "The difference is the dry of the elements that are in `D1' but not "+
    "in `D2'. So `"+~.name+"' removes (see `DryRemove_') all elements from "+
    "`D1' that are in `D2'.\n"+
    "Note: `D2' may be a list that is not a proper dry, in which case `Dry' "+
    "is silently applied to it."
  ), DryDifference_);
InstallMethod(
  rec(
  kind := "FUNCTION",
  name := "Difference_",
  sin  := [[set,"S1"],[list,"S2"]],
  sou  := [],
  short := "Change `S1' so that it becomes the difference of `S1' and `S2'.\n"+
    "The difference is the set of the elements that are in `S1' but not "+
    "in `S2'. So `"+~.name+"' removes (see `SetRemove_') all elements from "+
    "`S1' that are in `S2'.\n"+
    "Note: `S2' may  be a list that is not a proper set, in which case `Set' "+
    "is silently applied to it."
  ), SetDifference_);





###############
### alist.g ###
###############


#############################################################################
##
#F  AlistKeys( <alist> )
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="AlistKeys",
    sin:=[[alist,"A"]],
    opt:=[__FAILUREDOC],
    sou:=[[list,"keyl"]],
    short:="Return a list of keys of the alist `A'.",
    ex:=["A:=Alist([\"foo\",\"someval1\"],[\"bar\",\"someval2\"]);\n"+
         "AlistKeys(A);"],
    see:=[DocHash("AlistValues(alist)")]));

#############################################################################
##
#F  AlistValues( <alist> )
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="AlistValues",
    sin:=[[alist,"A"]],
    opt:=[__FAILUREDOC],
    sou:=[[list,"vall"]],
    short:="Return a list of values of the alist `A'.",
    ex:=["A:=Alist([\"foo\",\"someval1\"],[\"bar\",\"someval2\"]);\n"+
         "AlistValues(A);"],
    see:=[DocHash("AlistKeys(alist)")]));

#############################################################################
##
#F  Assoc( alist, any )
#F  Image( alist, any )
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Assoc",
    sin:=[[alist,"A"],[any,"key"]],
    opt:=[__FAILUREDOC],
    sou:=[[any,"val"]],
    short:="Return the value associated with `key' in the alist `A'.",
    ex:=["A:=Alist([\"foo\",\"someval1\"],[\"bar\",\"someval2\"]);\n"+
         "Assoc(A,\"bar\"); Assoc(A,25);"],
    see:=[]));
## there are complications with our internal Image fun
#InstallMethod(
#  rec(
#    kind:="FUNCTION",
#    name:="Image",
#    sin:=[[alist,"A"],[any,"key"]],
#    opt:=[__FAILUREDOC],
#    sou:=[[any,"val"]],
#    short:="Return the value associated with `key' in the alist `A'.",
#    ex:=["A:=Alist([\"foo\",\"someval1\"],[\"bar\",\"someval2\"]);\n"+
#         "Image(A,\"bar\"); Image(A,25);"],
#    see:=[]), Assoc);

#############################################################################
##
#F  Rassoc( alist, any )
#F  Preimages( alist, any )
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Rassoc",
    sin:=[[alist,"A"],[any,"val"]],
    opt:=[__FAILUREDOC],
    sou:=[[any,"key"]],
    short:="Return a list of keys whose associations are `val' in the alist `A'.",
    ex:=["A:=Alist([\"foo\",\"someval1\"],[\"bar\",\"someval2\"]);\n"+
         "Rassoc(A,\"someval1\"); Rassoc(A,25);"],
    see:=[]));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Preimages",
    sin:=[[alist,"A"],[any,"val"]],
    opt:=[__FAILUREDOC],
    sou:=[[any,"key"]],
    short:="Return a list of keys whose associations are `val' in the alist `A'.",
    ex:=["A:=Alist([\"foo\",\"someval1\"],[\"bar\",\"someval2\"]);\n"+
         "Preimages(A,\"someval1\"); Preimages(A,25);"],
    see:=[]), Rassoc);


#############################################################################
##
#F  AddAssoc( alist, any, any )
#F  AddAssoc( alist, list(any,any) )
#F  AddAssoc_( alist, any, any )
#F  AddAssoc_( alist, list(any,any) )
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="AddAssoc",
    sin:=[[alist,"A"],[any,"key"],[any,"val"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[[alist]],
    short:=
      "Associate `key' with `val' in alist `A' if `key' was not already present "+
      "and return the alist derived from this association or FAILURE in case `key' "+
      "already had an association in `A'.\n"+
      "Note: This does not affect `A'.",
    ex:=["A:=Alist();\n"+
         "AddAssoc(A,1,\"foo\");"],
    see:=[DocHash("AddAssoc_(alist,any,any)")]), _AddAssoc_alist_any_any);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Add",
    sin:=[[alist,"A"],[any,"key"],[any,"val"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[[alist]],
    short:=
      "Associate `key' with `val' in alist `A' if `key' was not already present "+
      "and return the alist derived from this association or FAILURE in case `key' "+
      "already had an association in `A'.\n"+
      "Note: This does not affect `A'.",
    ex:=["A:=Alist();\n"+
         "Add(A,1,\"foo\");"],
    see:=[DocHash("Add(alist,any,any)")]), _AddAssoc_alist_any_any, rec(WrapFormerFuns:=FALSE));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="AddAssoc_",
    sin:=[[alist,"A"],[any,"key"],[any,"val"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[],
    short:=
      "Associate `key' with `val' in alist `A' if `key' was not already present "+
      "and return FAILURE on failure.\n"+
      "Note: `A' is modified by side-effect.",
    ex:=["A:=Alist();\n"+
         "AddAssoc_(A,1,\"foo\"); A;"],
    see:=[DocHash("AddAssoc(alist,any,any)")]), _AddAssoc__alist_any_any);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Add_",
    sin:=[[alist,"A"],[any,"key"],[any,"val"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[],
    short:=
      "Associate `key' with `val' in alist `A' if `key' was not already present "+
      "and return FAILURE on failure.\n"+
      "Note: `A' is modified by side-effect.",
    ex:=["A:=Alist();\n"+
         "Add_(A,1,\"foo\"); A;"],
    see:=[DocHash("Add(alist,any,any)")]), _AddAssoc__alist_any_any, rec(WrapFormerFuns:=FALSE));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="AddAssoc",
    sin:=[[alist,"A"],[list,"keyval"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[[alist]],
    short:=
      "Associate `key' (taken as first element of `keyval') with `val' (taken "+
      "as the rest of `keyval') in alist `A' if `key' was not already present "+
      "and return the alist derived from this association or FAILURE in case `key' "+
      "already had an association in `A'.\n"+
      "Note: This does not affect `A'.",
    ex:=["A:=Alist();\n"+
         "AddAssoc(A,[2,\"bar\",\"and_baz\"]);"],
    see:=[DocHash("AddAssoc_(alist,list)")]), _AddAssoc_alist_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="AddAssoc_",
    sin:=[[alist,"A"],[list,"keyval"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[],
    short:=
      "Associate `key' (taken as first element of `keyval') with `val' (taken "+
      "as the rest of `keyval') in alist `A' if `key' was not already present "+
      "and return FAILURE in case of failure.\n"+
      "Note: `A' is modified by side-effect.",
    ex:=["A:=Alist();\n"+
         "AddAssoc_(A,[2,\"bar\",\"and_baz\"]); A;"],
    see:=[DocHash("AddAssoc(alist,list)")]), _AddAssoc__alist_list);


#############################################################################
##
#F  PutAssoc( <alist>, <any>, <any> ) 
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="PutAssoc",
    sin:=[[alist,"A"],[any,"key"],[any,"val"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[[alist]],
    short:=
      "Associate `key' with `val' in alist `A' and return the alist derived "+
      "from this association.\n"+
      "Note: This does not affect `A'.",
    ex:=["A:=Alist();\n"+
         "PutAssoc(A,1,\"foo\");"],
    see:=[DocHash("PutAssoc_(alist,any,any)")]), _PutAssoc_alist_any_any);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Put",
    sin:=[[alist,"A"],[any,"key"],[any,"val"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[[alist]],
    short:=
      "Associate `key' with `val' in alist `A' and return the alist derived "+
      "from this association.\n"+
      "Note: This does not affect `A'.",
    ex:=["A:=Alist();\n"+
         "Put(A,1,\"foo\");"],
    see:=[DocHash("Put_(alist,any,any)")]), _PutAssoc_alist_any_any);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="PutAssoc_",
    sin:=[[alist,"A"],[any,"key"],[any,"val"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[],
    short:=
      "Associate `key' with `val' in alist `A' and return FAILURE on failure.\n"+
      "Note: `A' is modified by side-effect.",
    ex:=["A:=Alist();\n"+
         "PutAssoc_(A,1,\"foo\"); A;"],
    see:=[DocHash("PutAssoc(alist,any,any)")]), _PutAssoc__alist_any_any);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Put_",
    sin:=[[alist,"A"],[any,"key"],[any,"val"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[],
    short:=
      "Associate `key' with `val' in alist `A' and return FAILURE on failure.\n"+
      "Note: `A' is modified by side-effect.",
    ex:=["A:=Alist();\n"+
         "Put_(A,1,\"foo\"); A;"],
    see:=[DocHash("Put(alist,any,any)")]), _PutAssoc__alist_any_any);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="PutAssoc",
    sin:=[[alist,"A"],[list,"keyval"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[[alist]],
    short:=
      "Associate `key' (taken as first element of `keyval') with `val' (taken "+
      "as second element of `keyval') in alist `A' and return the alist derived "+
      "from this association.\n"+
      "Note: This does not affect `A'.",
    ex:=["A:=Alist();\n"+
         "PutAssoc_(A,[2,\"bar\"]);"],
    see:=[DocHash("PutAssoc(alist,list)")]), _PutAssoc_alist_list);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="PutAssoc_",
    sin:=[[alist,"A"],[list,"keyval"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[],
    short:=
      "Associate `key' (taken as first element of `keyval') with `val' (taken "+
      "as second element of `keyval') in alist `A' and return FAILURE on failure.\n"+
      "Note: `A' is modified by side-effect.",
    ex:=["A:=Alist();\n"+
         "PutAssoc_(A,[2,\"bar\"]); A;"],
    see:=[DocHash("PutAssoc(alist,list)")]), _PutAssoc__alist_list);


#############################################################################
##
#F  RemAssoc( alist, any )
#F  RemAssoc_( alist, any )
#F  RemImage( alist, any )
#F  RemImage_( alist, any )
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="RemAssoc",
    sin:=[[alist,"A"],[any,"key"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[[alist]],
    short:=
      "Remove `key' and its association in alist `A' and return the alist derived "+
      "from this removal.\n"+
      "Note: This does not affect `A'.",
    ex:=["A:=Alist([1,\"foo\"],[2,\"bar\"]);\n"+
         "RemAssoc(A,1);"],
    see:=[DocHash("RemAssoc_(alist,any)")]));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Remove",
    sin:=[[alist,"A"],[any,"key"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[[alist]],
    short:=
      "Remove `key' and its association in alist `A' and return the alist derived "+
      "from this removal.\n"+
      "Note: This does not affect `A'.",
    ex:=["A:=Alist([1,\"foo\"],[2,\"bar\"]);\n"+
         "RemAssoc(A,1);"],
    see:=[DocHash("Remove_(alist,any)")]), RemAssoc, rec(WrapFormerFuns:=FALSE));
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="RemAssoc_",
    sin:=[[alist,"A"],[any,"key"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[],
    short:=
      "Remove `key' and its association in alist `A' and return FAILURE on failure "+
      "or SUCCESS on success.\n"+
      "Note: `A' is modified by side-effect.",
    ex:=["A:=Alist([1,\"foo\"],[2,\"bar\"]);\n"+
         "RemAssoc_(A,1); A;"],
    see:=[DocHash("RemAssoc(alist,any)")]));
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Remove_",
    sin:=[[alist,"A"],[any,"key"]],
    opt:=[__FAILUREDOC,
          __SUCCESSDOC],
    sou:=[],
    short:=
      "Remove `key' and its association in alist `A' and return FAILURE on failure "+
      "or SUCCESS on success.\n"+
      "Note: `A' is modified by side-effect.",
    ex:=["A:=Alist([1,\"foo\"],[2,\"bar\"]);\n"+
         "RemAssoc_(A,1); A;"],
    see:=[DocHash("Remove(alist,any)")]), RemAssoc_, rec(WrapFormerFuns:=FALSE));


#############################################################################
##
#F  Alist( )
#F  Alist( nof(list(any, any)) )
##
## documentation see lib/init-methods.g
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Alist",
    sin:=[[]],
    sou:=[[alist,"A"]],
    short:=
      "Create and return an empty association list `A'.",
    ex:=["A:=Alist();"],
    see:=[DocHash("Alist(nof(list))")]));
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name:="Alist",
    sin:=[[nof(list)]],
    sou:=[[alist,"A"]],
    short:=
      "Create and return an association list `A' along with some content.\n"+
      "The arguments are two-cell lists. The alist is built by taking the "+
      "first element of a list as key and the second element as associated "+
      "value.",
    ex:=["A:=Alist([1,\"foo\"],[2,\"bar\"]);"],
    see:=[DocHash("Alist()")]));


#############################################################################
##
#F  Function( <alist> ) 
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="Function",
    sin:=[[alist,"A"]],
    sou:=[[func]],
    short:=
      "Create a function (not a map!) whose `domain' is the keylist of `A' and "+
      "whose `co-domain' is the valuelist of `A' and return this function.",
    ex:=["A:=Alist([1,\"foo\"],[2,\"bar\"],[3,\"foobar\"]);\n"+
         "AF:=Function(A);\n"+
         "AF(1); AF(2); AF(3); AF(4);"],
    see:=[]), _Function_alist);


#############################################################################
##
#F  Function( <alist> ) 
##
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="MapAlist",
    sin:=[[func,"f"],[alist,"A"]],
    sou:=[[]],
    short:=
      "Apply `f' to all entries in alist `A' and return SUCCESS.\n"+
      "`f' is expected to take two arguments, the first one is bound "+
      "to the key of an alist element, the second one is bound to its "+
      "association.",
    ex:=["A:=Alist([1,\"foo\"],[2,\"bar\"],[3,\"foobar\"]);\n"+
         "f:=function(key,val)\n"+
         "Print(\"key is \",key,\", val is \",val,\"\\n\");\n"+
         "end;\n"+
         "MapAlist(f,A);"],
    see:=[DocHash("Apply(func,alist)")]), _MapAlist_func_alist);
InstallMethod(
  rec(
    kind:="FUNCTION",
    name:="MapAlist",
    sin:=[[alist,"A"],[func,"f"]],
    sou:=[[]],
    short:=
      "Apply `f' to all entries in alist `A' and return SUCCESS.\n"+
      "`f' is expected to take two arguments, the first one is bound "+
      "to the key of an alist element, the second one is bound to its "+
      "association.",
    ex:=["A:=Alist([1,\"foo\"],[2,\"bar\"],[3,\"foobar\"]);\n"+
         "f:=function(key,val)\n"+
         "Print(\"key is \",key,\", val is \",val,\"\\n\");\n"+
         "end;\n"+
         "MapAlist(A,f);"],
    see:=[DocHash("Apply(func,alist)")]), _MapAlist_alist_func);




##############
### term.g ###
##############

#############################################################################
##
#F  PrintString(<nof(string)> [, optarg])
##
InstallDocumentation(
  rec( 
    kind:= "FUNCTION",
    name:= "PrintString",
    sin := [[nof(string),"S"]],
    opt := [[elt-ord^rat,"Start",
             "Offset to indicate how many columns have already been printed "+
             "in the current line",rec(Default:="GetCurrentColumn()")]],
    sou := [[]],
    short := "Print a string with respect to the current term's columns and lines "+
      "definition.",
    ex := [],
    see := []
    ));





#####################
### doc.g/docui.g ###
#####################


#############################################################################
##
#F  DocGenHashByString( <string> )
##
InstallDocumentation(
  rec(
    kind  := "FUNCTION",
    name  := "DocGenHashByString",
    sin   := [[string,"docsig"]],
    sou   := [[string,"dochash"]],
    short := "Return the hash value a record with signature `docsig' would "+
      "have if added to the global documentation dry.\n"+
      "You may want to use this when using the InstallDocumentation or "+
      "MergeDocumentation macros in order to refer to other functions without "+
      "looking up the hash value.",
    ex:=["DocGenHashByString(\"DocGenHashByString(string)\");"],
    see:=[DocGenHashByString("DocGenHashByRecord(record)")]));

#############################################################################
##
#F  DocGenHashByRecord( <record> )
##
InstallDocumentation(
  rec(
    kind  := "FUNCTION",
    name  := "DocGenHashByRecord",
    sin   := [[record,"docrec"]],
    sou   := [[string,"dochash"]],
    short := "Return the hash value a record `docrec' would have if added "+
      "to the global documentation dry.\n"+
      "You may want to use this when using the InstallDocumentation or "+
      "MergeDocumentation macros in order to refer to other functions without "+
      "looking up the hash value.\n"+
      "Note: In general there is no need to provide the whole record as "+
      "argument, instead sufficient are the rec fields which are used to "+
      "compute the hash sum. Currently these are `kind' and `name' and in "+
      "some cases (OPERATION and FUNCTION) `sin' is also mandatory.",
    ex:=["DocGenHashByRecord(rec(kind:=\"FUNCTION\","+
      "name:=\"DocGenHashByRecord\","+
      "sin:=[[record]]));"],
    see:=[DocGenHashByString("DocGenHashByString(string)")]));

#############################################################################
##
#F  CheckDocumentation( <record> )
##
InstallDocumentation(
  rec(
    kind  := "FUNCTION",
    name  := "CheckDocumentation",
    sin   := [[record,"r"]],
    sou   := [],
    short := "Return true iff documentation in record 'r' tends to be correct."));
#############################################################################
##
#F  BlowUpDocumentation( <record> )
##
InstallDocumentation(
  rec(
    kind  := "FUNCTION",
    name  := "BlowUpDocumentation",
    sin   := [[record,"r"]],
    sou   := [],
    short := "Blow up documentation in record 'r' by adding useful fields."));


#############################################################################
##
#F  InstallDocumentation( <record> )
##
InstallDocumentation(
  rec(
    kind  := "FUNCTION",
    name  := "InstallDocumentation",
    sin   := [[record,"r"]],
    opt   := [__FAILUREDOC,
              [elt-alg^boo,"ForceAdd","Default: FALSE, indicate you want to add "+
                "or replace existing documentation."]],
    sou   := [[elt-alg^boo,"success"]],
    short := "Add documentation given by `r' to global documentation hash table.\n"+
      "The documentation in `r' is blown up and checked. Then it is tried to be "+
      "added with a dry operation (DryReplaceOrAdd) and thus overwrites existing "+
      "documentation iff the hash value computed by `r' is already in the global "+
      "dry, and is appended otherwise.",
    see := [DocGenHashByRecord(rec(kind:="FUNCTION",
                                   name:="BlowUpDocumentation",
                                   sin:=[[record]])),
            DocGenHashByRecord(rec(kind:="FUNCTION",
                                   name:="CheckDocumentation",
                                   sin:=[[record]]))]));
#############################################################################
##
#F  MergeDocumentation( <record> )
##
InstallDocumentation(
  rec(
    kind  := "FUNCTION",
    name  := "MergeDocumentation",
    sin   := [[record,"r"]],
    opt   := [__FAILUREDOC,
              [any,"Success","Default: TRUE, indicate what to return in case of success"],
              [any,"Add","Default: FALSE, add `r' to documentation dry in either case"]],
    sou   := [],
    short := "Merge documentation given (even partially) by `r' to global "+
      "documentation hash table.\n"));

#############################################################################
##
#F  DocHash(<string>)
##
InstallDocumentation(
  rec(
    kind  := "FUNCTION",
    name  := "DocHash",
    sin   := [[string,"s"]],
    sou   := [[string,"hash"]],
    short := "Return the hash value used to identify a function specified by 's'. "+
             "The string 's' must be of the form \"functionname(typearg1,typearg2,...)\" or "+
             "\"type\" or \"keyword\".",
    ex := ["x_s := DocHash(\"GCD(elt-ord^rat,elt-ord^rat)\"););",
           "x_s := DocHash(\"record\");",
           "x_s := DocHash(\"operations\");"]));

#############################################################################
##
#F  Help(<string>)
##
InstallDocumentation(
  rec(
    kind  := "FUNCTION",
    name  := "DocHash",
    sin   := [[string,"s"]],
    sou   := [],
    short := "'Help(\"helpquery\")' is called when '?helpquery' is entered at the "+
             "prompt.",
    ex := ["Help(\"documentation\");"]));


##############
### init.g ###
##############

#############################################################################
##
#F  CheckArgs( <list>, <list>, <list> )
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name :="CheckArgs",
    sin  :=[[list,"arglist"],[list,"argnames"],[list,"defaults"]],
    sou  :=[[record]],
    short:="Traverse through `arglist' and bind arguments to argument names in "+
      "`argnames'. If some arguments are not provided bind them to values from "+
      "`defaults'. Return the resulting record.",
    see  :=[DocGenHashByString("HasOptarg(list)"),
            DocGenHashByString("ExtractOptarg(list)")]));
#############################################################################
##
#F  HasOptarg( <list> )
##
InstallDocumentation(
  rec(
    kind := "KEYWORD",
    name := "Optional Arguments",
    short :=
"Many KASH3 functions take optional arguments.  These are passed to a function "+
"by passing a record as a last argument to the function. ",
    see  :=[DocGenHashByString("ExtractOptarg(list)"),
            DocGenHashByString("HasOptarg(list)"),
            DocGenHashByString("CheckArgs(list,list,list)")]));
    
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name :="HasOptarg",
    sin  :=[[list,"arglist"]],
    sou  :=[[elt-alg^boo]],
    short:="Return TRUE iff arglist's last argument is an optional argument "+
      "record.",
    see  :=[DocGenHashByString("ExtractOptarg(list)"),
            DocGenHashByString("CheckArgs(list,list,list)")]));
#############################################################################
##
#F  ExtractOptarg( <string> )
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name :="ExtractOptarg",
    sin  :=[[list,"arglist"]],
    sou  :=[[record]],
    short:="Return arglist's last argument if it is an optional argument, "+
      "FAILURE otherwise otherwise.",
    see  :=[DocGenHashByString("ExtractOptarg_(list)"),
            DocGenHashByString("HasOptarg(list)"),
            DocGenHashByString("CheckArgs(list,list,list)")]));
#############################################################################
##
#F  ExtractOptarg_( <string> )
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name :="ExtractOptarg_",
    sin  :=[[list,"arglist"]],
    sou  :=[[record]],
    short:="Return and remove arglist's last argument if it is an optional "+
      "argument, FAILURE otherwise.\n "+
      "Note: This is the destructive version of ExtractOptarg.",
    see  :=[DocGenHashByString("ExtractOptarg(list)"),
            DocGenHashByString("HasOptarg(list)"),
            DocGenHashByString("CheckArgs(list,list,list)")]));
#############################################################################
##
#F  Optarg( <list>, <list>, <list> )
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name :="Optarg",
    sin  :=[[list,"arglist"],[list,"optarg_names"],[list,"defaults"]],
    sou  :=[[record]],
    short:="Process optional arguments.  Extract optional arguments record  from 'arglist'."+
           "Set missing entries (from 'optarg_names') to default values from "+
           "'defaults'.",
    see  :=[DocGenHashByString("ExtractOptarg(list)"),
            DocGenHashByString("HasOptarg(list)"),
            DocGenHashByString("CheckArgs(list,list,list)")]));
#############################################################################
##
#F  Read( <string> )
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name :="Read",
    sin  :=[[string,"filename"]],
    sou  :=[],
    short:="Read a file 'filename' containing KASH commands.",
    long :="The file 'filename' must both existing and readable."+
      "KASH looks first in the given path, then in the current directory "+
      "and finally in $LIBNAME../src.",
    see  :=[DocGenHashByString("ReadLib(string)")]));
#############################################################################
##
#F  ReadLib( <string> )
##
InstallDocumentation(
  rec(
    kind:="FUNCTION",
    name :="ReadLib",
    sin  :=[[string,"lib"]],
    sou  :=[],
    short:="Same as `Read', but here the file should be in the KASH lib "+
      "directory and it must have the extension  .g .",
    see  :=[DocGenHashByString("Read(string)")]));

#############################################################################
##
#K  arg
##
InstallDocumentation(
  rec(
    kind:="KEYWORD",
    name :="arg",
    syntax := "function(arg) ... end;",
    short := "Collapse arbitrary many arguments to a list of arguments and "+
      "pass it to arg.",
    long := "When used as (only) argument in a function's declaration this so "+
      "defined function accepts any number of arguments. "+
      "Arguments passed to the function at call-time are gathered into a "+
      "list whose value becomes `arg' in the function body.\n"+
      "Note: This will not work on abbreviated function declarations, like "+
      "`arg->arg[1];'.\n"+
      "Note: Also, the function keyword will not collect rests of arguments "+
      "into the arg argument, that is `function(some, arg) return TRUE; end;' "+
      "is a valid function which takes exactly two arguments, `arg' has no "+
      "no special meaning here (yet).",
    ex := ["x_f := function(arg) return arg; end;\n"+
           "x_f(1,2.3,\"hi mom\",[12,3]);\n"+
           "x_f(6);"]));

