the OO metaphor
Ulf Wiger
etxuwig@REDACTED
Wed Nov 29 11:00:10 CET 2000
On Tue, 28 Nov 2000, Vlad Dumitrescu wrote:
>The "thread thread" is very interesting, and talking about OO
>reminded me of an idea I got... I think it's not a very bad one, so
>I will share it with you, to see what you think.
>
>The OO methodology can be easily applied to Erlang, once one gets to
>ffel the pulse of the language. There is however one thing that is
>missing, and that I think it could be useful. That thing is
>inheritance.
I might then as well share something that I started hacking on
a few weeks ago. It seems to have come to a stop, so this might
be a good time to see if there's any interest in continuing...
I called it system_erlang. I tried to address the following:
- my old idea of extending the receive statement to automatically
handle system messages
- API inheritance, resolved at module load time
- fast-path execution, inspired by work I've seen on forwarding
engines, the Erlang processor, and the new filtering mechanisms in
OTP R7B (also Thomas Lingren's ongoing work.)
Comments are much appreciated.
/Uffe
%% Sample erlang module
-module(syserl).
-export([foo/0,
bar/0]).
%-import_directives(otp, [$extend_receive/1]).
%-export_to(Module, [Function/Arity]).
%-bounded_time([Function/Arity]).
%%% About system directives
%%% When building large complex erlang systems, one often wants to control
%%% the use of interfaces and seamlessly add support for system messages.
%%%
%%% Richard O'Keefe's suggestion of -export_to/2 is a good idea, e.g.
%%% because it allows hiding of "internal" exports, and restricted use of
%%% functions exported for a special purpose (e.g. application:set_env/3).
%%%
%%% I'd also like to be able to inherit interfaces from another module:
%%% an example is when writing a mnesia access module in order to redefine
%%% only a few access functions in mnesia; today one must redefine them all,
%%% even if the majority of functions will simply call the default mnesia
%%% function. This forces the maintainer of a mnesia access module to update
%%% their module every time a new access function is added to mnesia - even
%%% if this particular function is of no interest to the access module in
%%% question.
%%%
%%% Redefining message reception is difficult to do seamlessly:
%%% - if it's done in a library module, there is no room for selective receive
%%% - if it's done via a macro, variable binding becomes a problem. Also one
%%% must implement all the sys.erl callbacks, which is error prone.
%%%
%%% My approach is to introduce system directives, allowing each module to
%%% "enhance" keywords and inherit interfaces. In the example below, I have
%%% defined a keyword, system_receive, which can be used in place of 'receive'.
%%% It should be possible to also redefine 'receive', but most likely, the
%%% special feature of handling system messages would be used only in a few
%%% functions (the main event loop or certain states.)
%%% The interface inheritance could also mean that I wouldn't have to write
%%% the special sys.erl callback functions, which eliminates a source of
%%% errors.
%%%
%%% These system directives look pretty much like normal erlang functions,
%%% (except for the illegal function names) but are callable only by the VM.
%%% For this, the compiler may have to insert some helper function to help
%%% the loader make the calls (e.g. $fast_path/2 needs to be called once for
%%% each function.)
%%%
%%% An issue to discuss is how/if to make a distinction between compiler
%%% directives and system directives. For example, inheriting the interface
%%% of another module should be a system directive, in the sense that it
%%% should be resolved at runtime - not compile-time. Enabling fast-path
%%% execution might be handled by the compiler, but this requires knowledge
%%% about other modules, if we are to allow inter-module calls in fast-path
%%% processing. Making it a system directive would probably imply some kind
%%% of JIT.
%%% System directives.
%%% So far, we define four system directives:
%%% - $extend_receive(MyReceiveKeyword) -> ...<receive pattern>....
%%% This is used to define our own message reception semantics. The most
%%% useful variant will be to
%%% - $receive(), which is used in $extend_receive/1 to mark where the
%%% original receive clauses go.
%%%
%%% - $inherit_api(FromModule) -> all | [Exceptions].
%%% This is used to include the exported functions of FromModule as
%%% part of the exported functions in this module.
%%%
%%% - $fast_path(Function, Arity) -> hard | {hard, ExitFunction} | soft | none.
%%% This is used to identify functions that are candidates for fast-path
%%% compilation. The return value specifies what should happen if
%%% fast-path execution fails (which could possibly be when it
%%% encounters a side-effect or a function of unknown complexity):
%%% - 'hard' means simply exit;
%%% - {hard, ExitFunction} means that ExitFunction should be called
%%% (Example: a device processor performs fast-path analysis; failure
%%% leads to the packet being sent to a (slow path) control processor)
%%% - 'soft' means that fast-path failure triggers a slow-path
%%% (normal erlang) re-run
%%% - 'none' means normal erlang - allowed for completeness only.
$extend_receive(system_receive) ->
receive
Msg when element(1, Msg) == system, size(Msg) == 6 ->
sys:handle_system_messages(...);
$receive()
end.
$inherit_api(foo) ->
%% inherit all exported functions from foo.erl, except foo:fooey/1, which
%% is redefined in our module (runtime error if no such function is
%% exported), and foo:buggy/0, which is not available through this module.
%% syserl:buggy() will IOW cause exit({undef, _}).
[{redefine, [fooey/1]},
{exclude, [buggy/0]}];
$inherit_api(bar) ->
%% no special instructions, i.e. inherit all exported functions from bar.erl
all.
--
Ulf Wiger tfn: +46 8 719 81 95
Senior System Architect mob: +46 70 519 81 95
Strategic Product & System Management ATM Multiservice Networks
Data Backbone & Optical Services Division Ericsson Telecom AB
More information about the erlang-questions
mailing list