I don't think dynamic scoping is a good idea, but I wanted to point out that it does have some advantages:

- Sometimes you actually do want to change one of a large number of parameters for the dynamic extent of a single function call without having to make all of them parameters to that function. Classic examples are turning logging on for a single function call, changing the pen color or clipping region for a call to a subroutine that draws some kind of graphic, and running a function with the output redirected to a memory buffer instead of stdout. Dynamic scoping works great for this. My .emacs.d/init.el has an example where I temporarily set the "deactivate-mark" variable to a true value while I invoke some search and replace functions which would normally deactivate the mark, and another example where I temporarily set the "case-fold-search" variable to a false value so that the searches invoked from there will be case-sensitive.

That said, PostScript solves this problem differently, using a graphics context stack and gsave/grestore operators to enable you to make local changes to that context. Languages that support exceptions for normal control flow (as opposed to aborting the job or whatever) need some kind of defer/RAII/context-manager approach to making sure you don't forget to call grestore during the exception unwinding.

- As the article explains, dynamic scoping can be more efficient, but it doesn't explain why. We usually read variables more frequently than we supply them with values as parameters. In a single-threaded environment, dynamic scoping allows you to compile a read of a variable as a load from the fixed memory location of that variable, even if it's a local variable, even if your functions are recursive. Static scoping, by contrast, requires you to compile reads of your local variables as indexed loads from a frame pointer which points at your function's activation record, again unless you forbid recursion. The indexed load involves an addition of a constant to a register to compute the address to fetch from, and until the 1980s this actually made your program run slower. (Nowadays it just makes your program toggle more transistors, since the addition can nearly always be computed in parallel with other operations, and it probably isn't a significant contribution to total power consumption.)

Carrying this logic to the extreme, Multics Emacs (and I think GNU Emacs as a spiritual descendant) would swap in the values of not only function-local variables in this way but all the buffer-local variables whenever you switched buffers. The logic was that Lisp code would read the variables considerably more often than you switched buffers, so it was worth making a buffer switch slower to make the Lisp code run faster.

(There's another way to implement dynamic scoping called "deep binding", but I don't know of real systems that used it.)

Dynamic binding originated as a bug in the Lisp interpreter — you'll note that it's in both McCarthy's original paper and the Lisp 1.5 metacircular interpreter — but the divergence of its semantics from the static-scoping semantics of the λ-calculus weren't appreciated until later.

Also, as a side note, it's pretty fucking sad that it's 2018 and we're still dealing with language implementations on a daily basis that do things like box all their fucking fixnums, incurring not only unnecessary inefficiency but also unnecessary memory allocation and nondeterminism, so that adding two small integers can throw an out-of-memory error or produce a timing information leak that reveals secret information to an attacker. CPython, I'm looking at you, you fucking piece of shit.