An environment is simply a list of binding pairs - consisting of a variable name and a value. New bindings are always added to the front of the list. When eval encounters a variable, it searches through the environment for the first binding pair that contains that atom, and returns the associated value. Deep binding can clearly be much less efficient than shallow binding, particularly if the list of bindings is long and the desired variable is far down the list. However, it does facilitate certain other capabilities that are desirable, and so is the one generally used in modern LISP interpreters.
Many LISP implementations incorporate a compiler as well as an interpreter.
In compiled LISP, the effect of dynamic binding can be had without the necessity for a run-time search, because the compiler can calculate where in the environment the binding will be found and can generate code to go there directly. It turns out that the answer to this question varies, depending on what LISP implementation is used. In particular, the place where the difference will occur is in printing the value of v in f2. F2 does not have a variable v. A global v, created by the setq in main.