4 ms·
Perl has #1, it's called "local". Any "our" global variable can be automatically overridden... And not just our variables but also subroutine calls can be loca
by draegtun 16y ago
Perl has #1, it's called "local". Any "our" global variable can be automatically overridden...
And not just our variables but also subroutine calls can be localised in the scope:
sub bar { 'bar' }
sub baz { bar() }
sub foo {
no warnings 'redefine';
local *bar = sub { 'My Bar' };
baz();
}
say foo(); # => 'My Bar'
say bar(); # => 'bar'
say baz(); # => 'bar'
Thus you have localised monkey patching.
- ekiru 16y agoAnd array/hash slices/elements, including the deletion of a key.
- sedachv 16y agoOnce you have dynamically scoped variables, you can implement dynamically scoped functions. There's a really great paper by Pascal Costanza showing how to to this, and why it's the mechanism behind aspect-oriented programming (no, it's not just monkey-patching!): http://www.scribd.com/doc/47747298/Dynamically-Scoped-Functions-as-the-Essence-of-AOP http://www.scribd.com/doc/47747298/Dynamically-Scoped-Functi... You can generalize this to dynamically scoped object slots or whatever else you want, which Pascal does in the ContextL library: http://common-lisp.net/project/closer/contextl.html http://common-lisp.net/project/closer/contextl.html Actually, you don't even need built-in dynamic scoping, you can emulate it using unwind-protect (try-finally), which can itself be emulated: http://home.pipeline.com/~hbaker1/MetaCircular.html http://home.pipeline.com/~hbaker1/MetaCircular.html Once you have all that, you can implement Common Lisp's condition system. Here's Red Daly's implementation for JavaScript (Parenscript): https://github.com/gonzojive/paren-psos/commit/6578ad223515dc2c1ddf49346f4baf7c3bee37c4 https://github.com/gonzojive/paren-psos/commit/6578ad223515d... Of course, none of this is very useful without macros. For the condition system, you also have to be careful because any intermediate function that doesn't follow the protocol might swallow the exception. The reason you want dynamic scoping is because it completely obviates the need for dependency injection or the service locator pattern. DI is IMO by far the stupidest fad in object-oriented programming, which is no small feat. The Common Lisp condition system is great for doing things like writing network libraries. For example, an HTTP client library can throw any exception, like timeout, transfer error, encoding error, whatever, and offer a restart to let your retry the request (in just one place, independent of the exceptions). If you just want to retry but don't care why the thing failed, you do that. If you don't care about retrying, you just catch the error and report it, or whatever you want. The other thing about the Common Lisp condition system is that it provides introspection on conditions and restarts. This means I can do things like offer correct condition support for programs running across thread (and, eventually, network) boundaries transparently in Eager Future2 (http://common-lisp.net/project/eager-future/ http://common-lisp.net/project/eager-future/), in a portable way. By contrast, it's going to be impossible for C++ libraries using C++0x futures to be correct wrt exceptions without leaking their abstractions all over the calling code (if you don't wrap the exception, the information is not correct because who knows what thread/environment the future executed in, and if you do wrap it, you change the entire API).