anchor.diff:  do_list_ast([H | Hs], Tail) ->
     {cons, 0, H, do_list_ast(Hs, Tail)}.
   
  +%% @doc Replaces the first argument of a function with a pattern match.
  +%%
  +%% This function is used for deftype methods so that the fields are available
  +%% in the scope of the body of each method.
   -spec expand_first_argument(ast(), ast()) -> ast().
   expand_first_argument( {function, _, _, _, [ClauseAst]} = Function
                        , TypeTupleAst
  
positive.code: %%      to build Clojerl data types.
  -spec type_tuple(atom(), [ast()], [ast()], create | match) -> ast().
  type_tuple(Typename, AllFieldsAsts, HiddenFieldsAsts, TupleType) ->
    {MapField, Info} =
      case TupleType of
        create ->
          {map_field_assoc, {atom, 0, undefined}};
  
negative.code:   AccessorName = field_fun_name(FieldName),
    function_form(AccessorName, ClausesAsts).
  
  -spec create_function(atom(), [ast()], [ast()]) -> ast().
  create_function(Typename, AllFieldsAsts, HiddenFieldsAsts) ->
    MapVarAst    = {var, 0, map},
    GetAstFun    = fun(FName) ->
                       ArgsAst = [ MapVarAst
                                 , {atom, 0, FName}
                                 ],
                       application_mfa(clj_core, get, ArgsAst)
                   end,
  
    DissocFoldFun = fun({var, _, FName} = FieldAst, MapAst) ->
                        case lists:member(FieldAst, HiddenFieldsAsts) of
                          true  -> MapAst;
                          false ->
                            FAtom = {atom, 0, FName},
                            application_mfa(clj_core, dissoc, [MapAst, FAtom])
                        end
                    end,
  
    %% Coerce argument into a clojerl.Map
    EmptyMapAst   = erl_parse:abstract('clojerl.Map':new([])),
    ArgsListAst   = list_ast([EmptyMapAst, MapVarAst]),
    MergeCallAst  = application_mfa(clj_core, merge, [ArgsListAst]),
  
    ExtMapAst     = lists:foldl(DissocFoldFun, MergeCallAst, AllFieldsAsts),
  
    FieldsMapAst = { map
                   , 0
                   ,  [ { map_field_assoc
                        , 0
                        , {atom, 0, FieldName}
                        , case lists:member(FieldAst, HiddenFieldsAsts) of
                            true when FieldName =:= '__extmap' ->
                              ExtMapAst;
                            true ->
                              {atom, 0, undefined};
                            false ->
                              GetAstFun(FieldName)
                          end
                        }
                        || {var, _, FieldName} = FieldAst <- AllFieldsAsts
                      ]
                   },
    InfoAst      = {atom, 0, undefined},
    TupleAst     = type_tuple_ast(Typename, FieldsMapAst, InfoAst),
  
    BodyAst      = [TupleAst],
  
    ClausesAsts  = [{clause, 0, [MapVarAst], [], BodyAst}],
  
    function_form(create, ClausesAsts).
  
  -spec field_fun_name(atom()) -> atom().
  field_fun_name(FieldName) when is_atom(FieldName) ->
    list_to_atom("-" ++ atom_to_list(FieldName)).
  