Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

uses for dynamic scope?

Tags:

scope

lisp

elisp

I've been getting my hands wet with emacs lisp, and one thing that trips me up sometimes is the dynamic scope. Is there much of a future for it? Most languages I know use static scoping (or have moved to static scoping, like Python), and probably because I know it better I tend to prefer it. Are there specific applications/instances or examples where dynamic scope is more useful?

like image 414
hatmatrix Avatar asked Jun 05 '10 06:06

hatmatrix


1 Answers

There's a good discussion of this issue here. The most useful part that pertains to your question is:

Dynamic bindings are great for modifying the behaviour of subsystems. Suppose you are using a function ‘foo’ that generates output using ‘print’. But sometimes you would like to capture the output in a buffer of your choosing. With dynamic binding, it’s easy:

(let ((b (generate-new-buffer-name " *string-output*"))))
    (let ((standard-output b))
      (foo))
    (set-buffer b)
    ;; do stuff with the output of foo
    (kill-buffer b))

(And if you used this kind of thing a lot, you’d encapsulate it in a macro – but luckily it’s already been done as ‘with-output-to-temp-buffer’.)

This works because ‘foo’ uses the dynamic binding of the name ‘standard-output’, so you can substitute your own binding for that name to modify the behaviour of ‘foo’ – and of all the functions that ‘foo’ calls.

In a language without dynamic binding, you’d probably add an optional argument to ‘foo’ to specify a buffer and then ‘foo’ would pass that to any calls to ‘print’. But if ‘foo’ calls other functions which themselves call ‘print’ you’ll have to alter those functions as well. And if ‘print’ had another option, say ‘print-level’, you’d have to add that as an optional argument as well… Alternatively, you could remember the old value of ‘standard-output’, substitute your new value, call ‘foo’ and then restore the old value. And remember to handle non-local exits using ‘throw’. When you’re through with this, you’ll see that you’ve implemented dynamic binding!

That said, lexical binding is IMHO much better for 99% of the cases. Note that modern Lisps are not dynamic-binding-only like Emacs lisp.

  • Common Lisp supports both forms of binding, though the lexical one is used much more
  • The Scheme specification doesn't even specify dynamic binding (only lexical one), though many implementations support both.

In addition, modern languages like Python and Ruby that were somewhat inspired by Lisp usually support lexical-binding in a straightforward way, with dynamic binding also available but less straightforward.

like image 58
Eli Bendersky Avatar answered Oct 07 '22 20:10

Eli Bendersky