
#############################################################################
##
#F  Position( alist, any )
##
## documentation see lib/init-methods.g
_Position_alist_any:=
  function(arg)
    local alis,key,optarg;
    CheckArgs(arg,["alis","key","optarg"],[,,__FAILSUCCREC]);
    alis:=__ARGREC.("alis");
    key:=__ARGREC.("key");
    optarg:=__ARGREC.("optarg");
    return DryPosition(alis.keys,key,optarg);
  end;


#############################################################################
##
#F  AlistKeys( alist )
##
## documentation see lib/init-docs.g
AlistKeys:=
  function(arg)
    local alis,optarg,keyl;
    CheckArgs(arg,["alis","optarg"],[,__FAILUREREC]);
    alis:=__ARGREC.("alis");
    optarg:=__ARGREC.("optarg");

    keyl:=_GetEntry_rec_string(alis,"keys",optarg);
    return keyl;
  end;


#############################################################################
##
#F  AlistValues( alist )
##
## documentation see lib/init-docs.g
AlistValues:=
  function(arg)
    local alis,optarg,vall;
    CheckArgs(arg,["alis","optarg"],[,__FAILUREREC]);
    alis:=__ARGREC.("alis");
    optarg:=__ARGREC.("optarg");

    vall:=_GetEntry_rec_string(alis,"base",optarg);
    return vall;
  end;


## the print function
_PrintAlist:=
  function(alis)
    Print("Alist on keys ",AlistKeys(alis));
  end;



#############################################################################
##
#F  Assoc( alist, any )
#F  Image( alist, any )
##
## documentation see lib/init-docs.g
Assoc:=
  function(arg)
    local alis,key,optarg,pos;

    CheckArgs(arg,["alis","key","optarg"],[,,__FAILUREREC]);
    alis:=__ARGREC.("alis");
    key:=__ARGREC.("key");
    optarg:=__ARGREC.("optarg");

    pos:=_Position_alist_any(alis,key);
    if IsSuccess(pos) then
      return alis[pos];
    else
      return _GetFailEntry(optarg);
    fi;
  end;


#############################################################################
##
#F  Rassoc( alist, any )
#F  Preimages( alist, any )
##
## documentation see lib/init-docs.g
Rassoc:=
  function(arg)
    local alis,val,optarg,pos;

    CheckArgs(arg,["alis","val","optarg"],[,,__FAILUREREC]);
    alis:=__ARGREC.("alis");
    val:=__ARGREC.("val");
    optarg:=__ARGREC.("optarg");

    pos:=Positions(alis.base,val);
    if IsSuccess(pos) then
      return _Apply_func_list(i->alis.keys[i],pos);
    else
      _GetFailEntry(optarg);
    fi;
  end;


#############################################################################
##
#F  AddAssoc( alist, any, any )
#F  AddAssoc( alist, list(any,any) )
#F  AddAssoc_( alist, any, any )
#F  AddAssoc_( alist, list(any,any) )
##
## documentation see lib/init-methods.g
_AddAssoc__alist_any_any:=
  function(arg)
    local alis,key,val,optarg,pos;

    CheckArgs(arg,["alis","key","val","optarg"],[,,,__FAILSUCCREC]);
    alis:=__ARGREC.("alis");
    key:=__ARGREC.("key");
    val:=__ARGREC.("val");
    optarg:=__ARGREC.("optarg");

    pos:=_Position_alist_any(alis,key);
    if IsSuccess(pos) then
      return _GetFailEntry(optarg);
    else
      DryAdd_(alis.keys,key);
      _Add__list_any(alis.base,val);
      return _GetSuccessEntry(optarg);
    fi;
  end;
_AddAssoc_alist_any_any:=
  function(arg)
    local alis,key,val,optarg,al;

    CheckArgs(arg,["alis","key","val","optarg"],[,,,__FAILSUCCREC]);
    alis:=__ARGREC.("alis");
    key:=__ARGREC.("key");
    val:=__ARGREC.("val");
    optarg:=__ARGREC.("optarg");

    al:=Copy(alis);
    _AddAssoc__alist_any_any(al,key,val,optarg);

    return al;
  end;
_AddAssoc__alist_list:=
  function(arg)
    local alis,keyval,optarg,key,val;

    CheckArgs(arg,["alis","keyval","optarg"],[,,__FAILSUCCREC]);
    alis:=__ARGREC.("alis");
    keyval:=__ARGREC.("keyval");
    optarg:=__ARGREC.("optarg");

    key:=_GetEntry_list_eor(keyval,1);
    val:=Butfirst(keyval);
    if IsSuccess(key) and IsSuccess(val) then
      return _AddAssoc__alist_any_any(alis,key,val,optarg);
    else
      return _GetFailEntry(optarg);
    fi;
  end;
_AddAssoc_alist_list:=
  function(arg)
    local alis,keyval,optarg,al;

    CheckArgs(arg,["alis","keyval","optarg"],[,,__FAILSUCCREC]);
    alis:=__ARGREC.("alis");
    keyval:=__ARGREC.("keyval");
    optarg:=__ARGREC.("optarg");

    al:=Copy(alis);
    _AddAssoc__alist_list(al,keyval,optarg);
    return al;
  end;


#############################################################################
##
#F  PutAssoc( alist, any, any )
#F  PutAssoc( alist, list(any,any) )
#F  PutAssoc_( alist, any, any )
#F  PutAssoc_( alist, list(any,any) )
##
## documentation see lib/init-methods.g
_PutAssoc__alist_any_any:=
  function(arg)
    local alis,key,val,optarg,pos;

    CheckArgs(arg,["alis","key","val","optarg"],[,,,__FAILSUCCREC]);
    alis:=__ARGREC.("alis");
    key:=__ARGREC.("key");
    val:=__ARGREC.("val");
    optarg:=__ARGREC.("optarg");

    pos:=_Position_alist_any(alis,key);
    if IsSuccess(pos) then
      alis[pos]:=val;
    else
      DryAdd_(alis.keys,key);
      _Add__list_any(alis.base,val);
    fi;
    return _GetSuccessEntry(optarg);
  end;
_PutAssoc_alist_any_any:=
  function(arg)
    local alis,key,val,optarg,al;

    CheckArgs(arg,["alis","key","val","optarg"],[,,,__FAILSUCCREC]);
    alis:=__ARGREC.("alis");
    key:=__ARGREC.("key");
    val:=__ARGREC.("val");
    optarg:=__ARGREC.("optarg");

    al:=Copy(alis);
    _PutAssoc__alist_any_any(al,key,val,optarg);

    return al;
  end;
_PutAssoc__alist_list:=
  function(arg)
    local alis,keyval,optarg,key,val;

    CheckArgs(arg,["alis","keyval","optarg"],[,,__FAILSUCCREC]);
    alis:=__ARGREC.("alis");
    keyval:=__ARGREC.("keyval");
    optarg:=__ARGREC.("optarg");

    key:=_GetEntry_list_eor(keyval,1);
    val:=Butfirst(keyval);
    if IsSuccess(key) and IsSuccess(val) then
      return _PutAssoc__alist_any_any(alis,key,val,optarg);
    else
      return _GetFailEntry(optarg);
    fi;
  end;
_PutAssoc_alist_list:=
  function(arg)
    local alis,keyval,optarg,al;

    CheckArgs(arg,["alis","keyval","optarg"],[,,__FAILSUCCREC]);
    alis:=__ARGREC.("alis");
    keyval:=__ARGREC.("keyval");
    optarg:=__ARGREC.("optarg");

    al:=Copy(alis);
    _PutAssoc__alist_list(al,keyval,optarg);
    return al;
  end;



#############################################################################
##
#F  RemAssoc( alist, any )
#F  RemAssoc_( alist, any )
#F  RemImage( alist, any )
#F  RemImage_( alist, any )
##
## documentation see lib/init-methods.g
RemAssoc_:=
  function(arg)
    local alis,key,optarg,pos;

    CheckArgs(arg,["alis","key","optarg"],[,,__FAILSUCCREC]);
    alis:=__ARGREC.("alis");
    key:=__ARGREC.("key");
    optarg:=__ARGREC.("optarg");

    pos:=_Position_alist_any(alis,key);
    if IsSuccess(pos) then
      Remove_(alis.keys,pos);
      Remove_(alis.base,pos);
      return _GetSuccessEntry(optarg);
    else
      return _GetFailEntry(optarg);
    fi;
  end;
RemAssoc:=
  function(arg)
    local alis,key,optarg,al;

    CheckArgs(arg,["alis","key","optarg"],[,,__FAILSUCCREC]);
    alis:=__ARGREC.("alis");
    key:=__ARGREC.("key");
    optarg:=__ARGREC.("optarg");

    al:=Copy(alis);
    RemAssoc_(al,key,optarg);
    return al;
  end;


#############################################################################
##
#F  Alist( )
#F  Alist( nof(list(any, any)) )
##
## documentation see lib/init-methods.g
Alist:=
  function(arg)
    local alis,keys,optarg,vallist,i,k,v;
    keys:=Dry([]);
    vallist:=[];

    optarg := ExtractOptarg(arg);

    for i in arg do
      k := _GetEntry_list_eor(i,1);
      v := _GetEntry_list_eor(i,2);
      if IsSuccess(k) and IsSuccess(v) then
        if DryAdd_(keys,k)=SUCCESS then
          _Add__list_any(vallist,v);
        fi;
      fi;
    od;

    alis:=
      rec(
        base:=vallist,
        keys:=keys,
        type:=alist,
        operations:=
          rec(
            Print:=_PrintAlist));

    return alis;
  end;


#############################################################################
##
#F  Function( <alist> ) 
##
## documentation see lib/init-methods.g
_Function_alist:=
  function(arg)
    local alis,outeroptarg;

    CheckArgs(arg,["alis","outeroptarg"],[,__FAILUREREC]);
    alis:=__ARGREC.("alis");
    outeroptarg:=__ARGREC.("outeroptarg");

    return
      function(arg)
        local key,optarg;
        CheckArgs(arg,["key","optarg"],[,outeroptarg]);
        key:=__ARGREC.("key");
        optarg:=__ARGREC.("optarg");
        return Assoc(alis,key,optarg);
      end;
  end;


#############################################################################
##
#F  List( <func>, <alist> )
##  Attention, the overloader shall handle this
##
## documentation see lib/init-methods.g
_Apply_func_alist:=
  function(fun,alis)
    local res, i;

    res:=Alist();
    for i in [1.._Size_list(alis.keys)] do
      _PutAssoc__alist_any_any(res,alis.keys[i],fun(alis.base[i]));
    od;
    return res;
end;
_Apply_alist_func:=
  function(alis,fun)
    return _Apply_func_alist(fun,alis);
end;
_Apply__func_alist:=
  function(fun,alis)
    local res, i;

    for i in [1.._Size_list(alis.keys)] do
      _PutAssoc__alist_any_any(alis,alis.keys[i],fun(alis.base[i]));
    od;
    return SUCCESS;
end;
_Apply__alist_func:=
  function(alis,fun)
    return _Apply__func_alist(fun,alis);
end;


#############################################################################
##
#F  MapAlist( <func>, <alist> ) 
#F  MapAlist_( <func>, <alist> ) 
##
## documentation see lib/init-methods.g
_MapAlist_func_alist:=
  function(arg)
    local fun,alis,i;
    CheckArgs(arg,["fun","alis"],[]);
    fun:=__ARGREC.("fun");
    alis:=__ARGREC.("alis");
    for i in _GetEntry_rec_string(alis,"keys",rec(Fail:=[])) do
      fun(i,Assoc(alis,i));
    od;
  end;
_MapAlist_alist_func:=
  function(arg)
    local fun,alis,i;
    CheckArgs(arg,["alis","fun"],[]);
    fun:=__ARGREC.("fun");
    alis:=__ARGREC.("alis");

    _MapAlist_func_alist(fun,alis);
  end;
_MapAlist__func_alist:=
  function(arg)
    local fun,alis,i;
    CheckArgs(arg,["fun","alis"],[]);
    fun:=__ARGREC.("fun");
    alis:=__ARGREC.("alis");
    for i in _GetEntry_rec_string(alis,"keys",rec(Fail:=[])) do
      _PutAssoc__alist_any_any(alis,i,fun(i,Assoc(alis,i)));
    od;
  end;
_MapAlist__alist_func:=
  function(arg)
    local fun,alis,i;
    CheckArgs(arg,["alis","fun"],[]);
    fun:=__ARGREC.("fun");
    alis:=__ARGREC.("alis");

    _MapAlist__func_alist(fun,alis);
  end;
