Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Dynamic scope. Not really very strange but very unusual; not supported by many languages. AFAIK Perl and Lisp(ish) languages are the only ones. For example:

  sub foo {my $x='fish'; local $y='chips'; &bar;}

  sub bar {print "\$x is >$x< and \$y is >$y<\n";}
This will output

  $x is >< and $y is >chips<
It's quite handy - saves passing around a "context" object, for example. The remarkable thing is how few languages implement some form of it.


Dynamic scope is supported in older Lisps (eLisp is the only widely used variant with it), and a variety of scripting languages including PHP, Perl, TCL and vimsh (that's vim's internal scripting language). It is rarish because it has been recognized as a bad design, but it still turns up because it is easy to implement.


It is often recognized as bad design - though I don't think that's always fair. I thought of this because I was just reading some Java code that passed around a context object with all kinds of random things stuffed into it. It was, in effect, a way of simulating dynamic scope. There's a time and a place for everything. I'm sure dynamic scope can be horribly abused, but it's also nice to have in the toolbox for when you actually need to do what it does.


> eLisp is the only widely used variant with it

I think you mean it's the only widely used variant where it's the default. It's available in CL and Clojure when you want (need?) it.


And Haskell:

   import Control.Monad.Reader

    type Action = ReaderT String IO ()

    foo :: Action
    foo = do
      bar
      local (const "new state") bar
      bar

    bar :: Action
    bar = liftIO . putStrLn =<< ask

    > runReaderT foo "foo"
    foo
    new state
    foo


As well as scheme.


How does tcl, php, and vimscript support dynamic scoping? Examples please.

IIRC common lisp supports dynamic scoping too -- it defaults to lexical scoping though.


If you ever tried implementing a language, you'll see that dynamic scope is actually much easier. So it's not that language x doesn't implement dynamic scope. It's that language x doesn't actually implement lexical scope so it's left with dynamic scope :)


I'm not sure I understand your sentence (did you mean language x does implement dynamic scope?), but I feel obliged to mention Perl offers lexical scoping as well--within each file and each block.


If you're a lazy language designer dynamic scope sort of emerges from the design proces while one really has to do extra work to support lexical scoping in a language.


Perl 5 has dynamic scoping for backward compatibility with Perl 4, which had only dynamic scoping, and not only that, it botched it so that this code didn't work right:

    sub greet {
        local ($who) = @_;
        print "hello, $who\n";
    }

    $who = "world";
    &greet($who);
This would print, "hello, " with a newline, due to a design bug called "variable suicide", which has been fixed in newer Perls.

Needless to say, this made the extract-subroutine refactoring quite a bit more trouble in Perl 4.


It doesn't just have it for backwards compatibility, it's still a very useful feature in some cases:

    sub foo {
        local $ENV{HOME} = "/foo/bar";
        Code::I::Don't::Own();
    }
    foo();
Having dynamic scope here ensures that the foreign code will use the environment I want without me having to alter it.


Perl 6 also has dynamic scoping. But I don't think they kept it just for backward compatibility with Perl 4 & 5 :)

Here is another example where dynamic scoping can indeed be very useful:

    sub bar { 'bar' }
    sub baz { bar() }

    sub foo {
        no warnings 'redefine';
        local *bar = sub { 'My Bar' };
        baz();
    }

    say foo();   # => 'My Bar'
    say baz();   # => 'bar'




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: