anchor.diff: +%% @doc Nested scopes.
  +%%
  +%% Implements nested scopes through nested maps. This is heavily used
  +%% in all throughout the compilation process, from the reader to the
  +%% emitter.
   -module(clj_scope).
   
   -include("clojerl.hrl").
  
positive.code:            end,
    lists:foldl(PutFun, Scope, maps:keys(Map)).
  
  -spec update(any(), any(), scope()) -> scope() | not_found.
  update(Key, Value, Scope) ->
    do_update(Key, Value, Scope).
  
  -spec values(scope()) -> [any()].
  values(Scope) ->
    do_values([], Scope).
  
  -spec to_map(function(), scope()) -> any().
  to_map(Fun, Scope) ->
    do_to_map(Fun, #{}, Scope).
  
negative.code:                   , mappings => map()
                    }.
  
  %% @doc Creates a new empty scope.
  -spec new() -> scope().
  new() -> new(?NIL).
  
  %% @doc Creates a scope with an assigned parent.
  -spec new(scope() | ?NIL) -> scope().
  new(Parent) ->
   #{ parent   => Parent
    , mappings => #{}
    }.
  
  %% @doc Returns the parent of the current scope.
  -spec parent(scope()) -> scope() | ?NIL.
  parent(?NIL)  -> ?NIL;
  parent(Scope) -> maps:get(parent, Scope).
  
  %% @equiv get(Key, undefined, Scope)
  -spec get(any(), scope()) -> any().
  get(Key, Scope) ->
    get(Key, ?NIL, Scope).
  
  %% @doc Gets a value from the current scope or `Default' if not
  %% found.
  -spec get(any(), any(), scope()) -> any().
  get(Key, Default, Scope) ->
    do_get(Key, Default, Scope).
  
  %% @doc Checks whether `Key' is in the current scope.
  -spec contains(any(), scope()) -> boolean().
  contains(Key, Scope) ->
    do_contains(Key, Scope).
  
  %% @doc Adds a value to the current scope.
  -spec put(any(), any(), scope()) -> scope().
  put(Key, Value, Scope = #{mappings := Mappings}) ->
    Scope#{mappings => Mappings#{Key => Value}}.
  
  %% @doc Adds all values in `Map' to the current scope.
  -spec put(map(), scope()) -> scope().
  put(Map, Scope) ->
    PutFun = fun(Key, Acc) ->
  