How important is it to have catchalls and interceptors in a programming language

Ruby has method_missing.

What other languages have solid support for such interceptors?

There is much interest in considering catchalls for a future version of Javascript:
http://wiki.ecmascript.org/doku.php?id=strawman:catchalls

What are the pros and cons of having interceptors in a language?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Important

They are getting a lot of use in Smalltalk and Ruby, and I think that all object-oriented dynamic languages should offer them, because they can be extremely helpful (see Open, extensible object models for a fundamentalist viewpoint).

Oz has otherwise method

For another language that is less in the Smalltalk family, there is Oz. From CTM:

The otherwise method. The method head with label otherwise is a catchall that accepts any message for which no other method exists. For example:

meth otherwise(M)
   % Method body
end

A class can only have one method with head otherwise, otherwise there is a syntax error. If this method exists, then the object accepts any message. If no method is defined for the message, then the otherwise(M) method is called with the full message in M as a record. This mechanism allows to implement delegation, an alternative to inheritance explained in Section 7.3.4. This mechanism also allows making wrappers around method calls.

More fundamentalist

The language Im currently working on (Dawn), has a more fundamentalist approach (and worse some might add). At the risk of getting beaten down with a stick (since its not yet released) here is a description:

Each block or scope is an object. Each time an identifier is looked up, a method is called to look it up (you can say the there are no methods so the catch all is always called). It default behavior is like you would expect it to - it will traverse the list of methods/variables etc. and "return" the one referenced. If it does not find one it may call a catchall function to emulate the ruby functionality.

The difference is that ALL resources are treated in the same manner and libraries will allow the file system, URLs and hardware as internal variables or methods.

Does the answer not depend

Does the answer not depend on the type of language (e.g., statically typed or not)?

It is interesting how this design decision affect programming style, by the way.

Sorry I have nothing much to

Sorry I have nothing much to add but questions: What work is there on outfitting static type systems with catchall's/method missing or such?

Also, considering that there are common use cases for method missing, what devices exist in static type systems for these common usages? For example the times where I most want this(in Java, for reference) would be to create generic "wrappers" that delegate to another object(and doing something "interesting" before or after the delegation). Another example I have seen involves clever tricks with XML parsers that use catchall's(getters for attributes, etc.). I'm quite sure most LtU members can come up with better examples, but I do believe that many "use cases" of method missing might have another option that could more easily be statically typed.

Well, the worst example is probably ... in C/C++

Few think of the stdard facility as a catchall, and it suffers from numerous deficiencies:

1) No verification of the arguments whatsoever. stdarg provides a means for unpacking the argument list, but typically does no runtime checking, and requires the user pass in some specification of what the following arguments are (i.e. a format string).

2) Because of 1, the stdarg facility doesn't even support ... without at least one named argument. (You can declare functions of type foo(...), you just can't use stdarg to destructure them).

Most uses of ... are for one of two things, it seems: a) writing printf-style functions, and b) writing functions which take a null-terminated, variable-length argument list where all args are of the same type. a) has long been deprecated by iostream (but still lives on in much legacy code), and C++0x provides numerous features which should eliminate the need to use stdard for b.

... is useful as a catchall in two contexts:

1) In certain cases of template metaprogramming, when you need a catchall to get the thing to compile, and the catchall doesn't actually care what the arguments are.

2) The universal catch clause in exception handling, which catches any exception. As C++ lacks a top type, and as any value can be thrown to an exception handler (no need to subclass std::exception, even though this is the recommended practice), ... is used as "top" in this case. Of course, such an exception handler cannot access the passed-in value, with the exception (pun not intended) that a zero-argument throw statement will re-throw whatever it--useful for adding diagnostics to stack unwinding when an exception is thrown.

Bottom line: ... and stdard are probably good examples of what NOT to do, but you knew that already.

Ellipsis for C++ EH

A truly useful example for the '...' catchall in a handler exists in multi-language projects. If C++ code can be called from a language that is ignorant of the C++ EH unwinder, the other language may need to be protected from the unwinder. For example, when adding C++ extensions to a Python runtime, Boost.Python uses the ellipsis catch handler to protect the Python runtime from C++ unwinder, and translates the exception into an opaque Python exception type.

Of course, the top type could also serve this purpose. But then, isn't the top type itself a kind of catchall?

Top only refers to a single object

While exception throws are unary in C++, ... in the function-call context matches any number of arguments, whereas a function with signature foo (top), or foo (Object) in Java, matches any single argument, but not zero or two arguments.

Lua

In Lua, support for catchalls is quite flexible.
Tables, which are used to simulate O.O, may have associated "metamethods" to catch access to non-existing fields, such as undefined methods.

The following code sets the function `catchall` to be returned when a non-existing method is indexed:

setmetatable(obj, {__index=function() return catchall end})
obj:nonExistingMethod() -- becomes obj:catchall()

Lua provides several metamethods:
__index: called when a non-existing field is accessed
__newindex: called when a non-existing field is assigned
__call: called when the table is called as if it were a function
__add/__mul/etc: called when the table is used in arithmetic operations

Support for metamethods in Lua is essential, as an unlimited list of extensions to the languages are only possible with it.
The marginal runtime overhead is by far beaten by the "small kernel" nature of Lua.

Con: Future performance gains reduced?

What are its implications for runtime performance? My layman's understanding of the currently available JIT technologies (both trace compilers like Tracemonkey and semi-static compilers like Google V8) suggests that neither one will be able to fully accelerate calls through 'method missing.' While the dispatcher itself might get JIT-accelerated, the dispatch won't get resolved to its destination by the JIT.

Con: more than one version of the missing method?

might one hit N>1 helpful things that are trying to implement the same missing method, but for different purposes?

Bleh should be optionnal

catchalls has the *big* downside that they replace a compile time error with a runtime method call.

Nice if you need the flexibility but otherwise a big time waster in development.

So IMHO a language should have two method calls:
-a static one (.) which returns an error at compile time if object.method doesn't exist.
-a dynamic one (->) which call a 'catchall' method if object->method doesn't exist which gives more extensibility at the cost of needing more tests to catch runtime errors.

Then the developer is free to choose.

Oh, yeah and since we are at

Oh, yeah and since we are at it: why not switch between lazy and strict evaluation in Haskell using a compiler option? Why not designing each language s.t. features can be activated and deactivated? If the language has n features one gets 2^n different operational modes. The likelihood that 2 programs P1 and P2 are source compatible becomes 1/2^n.

Hmmm... maybe the idea is not that good after all.

I believe PHP is what you're

I believe PHP is what you're looking for. But then again, I think that agrees with your thesis: Not such a good idea.

Read again

I wasn't advocating a compiler switch but a language which include both kind of evaluations so the programmer can choose which one to use (possibly both), the language either providing different operators or using types qualifiers to define the evaluation rule used.

About lazy/strict debate: I remember some criticism about Haskell for providing only lazy evaluation which can create memory footprint issues, the solution proposed was to have both lazy and strict evaluation in the language with different keywords and let the programmer choose.

So IMHO language flexibility can be nice: a good example of language flexibility is D (which provides both strict and lazy evaluation for example), of course there are also counter-examples such as C++ and Perl which are probably the worst language 'designed'.

that's harsh

I've heard D has some really neat and powerfully productive and expressive features - and that it's a much cleaner language than C++ - but to indict the designers of C++ and perl in such a callous manner is a little harsh ;)

Higher-order discourse

Generally, comments such as "of course there are also counter-examples such as C++ and Perl which are probably the worst language 'designed'" are frowned upon on LtU. Not that C++ and Perl are immune from criticism (they are not); but simply declaring that something is of bad quality ("poorly designed", "sucks", "useless") doesn't say very much useful.

It is interesting to compare D and C++, given their similar lineage and design goals (Perl is another beast altogether), but simply claiming one is good and the other not doesn't enlighten.

I'm showing my ignorance

I'm showing my ignorance again, but this thread correlates to a recent interest of mine. I don't think it has to be this way. I'm quite sure there's work on static analysis of catchall's, or at least some set of programming language features that solve problems catchall's are typically used for that are also amenable to static analysis. But I don't know what this work would be, and so I hope some more knowledgeable LtU'er will see this thread and cite some papers to cure my ignorance.

optional sounds about right

I find this line of thinking quite intriguing - and while i've mused about this in the past, and while I clearly haven't given this enough thought, my sense was that it would be useful to have "dynamic" objects in a static language that are operated upon with a syntax similar to their statically typed counterparts (i.e. (.) vs (->)) - yet have semantics similar to javascript objects with the addition of catchalls (which I am mostly convinced are a very useful and productive feature to have in a language, but I wondered what a more sophisticated audience had to say about these constructs).