[eeps] New EEP draft: -discontiguous declaration
Raimo Niskanen
raimo+eeps@REDACTED
Fri May 27 16:00:51 CEST 2011
I'm sorry, we have changed EEP format into Markdown.
See EEP 33: http://www.erlang.org/eeps/eep-0033.html
I am not sure if this has been communicated properly,
so I would appreciate very much if you could reformat
your EEPs int Markdown according to EEP 33. Otherwise
I can't dig into that until sometime the next week...
Sorry about the inconveniance.
/ Raimo Niskanen, EEP Editor
On Fri, May 27, 2011 at 07:51:35PM +1200, ok@REDACTED wrote:
> Amongst other things,
> f(...) -> ...;
> -if(...).
> f(...) -> ...;
> -endif.
> f(...) -> ... .
> does not work. By stealing an idea from Grandfather Prolog,
> we can fix that.
>
> EEP: XXX
> Title: -discontiguous directive
> Version: $Revision: 14 $
> Last-Modified: $Date: 2007-06-29 16:24:01 +0200 (Fri, 29 Jun 2007) $
> Author: Richard A. O'Keefe <ok@REDACTED>
> Status: Draft
> Type: Standards Track
> Erlang-Version: R14B-4
> Content-Type: text/plain
> Created: 27-May-2011
> Post-History:
>
>
>
> Abstract
>
> A -discontiguous directive is to be added so that specified
> functions may be presented as more than one group of clauses,
> possibly separated by other directives and function clause
> groups.
>
>
> Specification
>
> A new directive
>
> -discontiguous( Name_And_Arity_List ).
>
> is added. Each function named in such a list must have at
> least one clause group in that module, and may have more.
> It remains an error for any function not named in such a
> list to have more than one clause group.
>
> A function named in a -discontiguous directive need not
> have more than one clause group. If it does, it is if
> the clause groups were moved together without reordering
> and the full stop of each group but the last changed to
> a semicolon. The compiler should make no comment about
> the existence of multiple clause groups or their fusion
> into single clause groups.
>
> The parser stage would do the regrouping and would not
> include any representation of the -discontiguous directive
> in its output, so that downstream tools would never know
> that -discontiguous had been there.
>
>
>
> Motivation
>
> There are three problems which a single mechanism can solve.
>
> The first is that Erlang has conditional compilation, but
> there is no really satisfactory to use it to select some
> but not all of the clauses of a function.
>
> The discontiguous directive allows you to write
>
> -discontiguous([f/3]).
>
> f(a, X, Y) -> .... .
> -if(Cond).
> f(b, X, Y) -> .... .
> -endif.
> f(c, X, T) -> .... .
>
> The second may be called "topic-oriented programming".
> It relates to human structuring of code around the
> data values computed on rather than the code they compute.
> I have found this in dealing with a virtual machine: I've
> wanted to place the code that assembles an instruction,
> the code that peephole optimises it, the code that encodes
> it into memory, and the code that interprets it into one
> place (involving different function), rather than organising
> it by function, thus scattering related information the
> length and breadth of the module.
>
> It may be clearest to start with an example. The code
> in erl_syntax.erl reads:
>
> -type syntaxTree() :: #tree{} | #wrapper{} | tuple().
>
> %% All `erl_parse' tree nodes are represented by tuples
> %% whose second field is the position information (usually
> %% an integer), *with the exceptions of*
> %% `{error, ...}' (type `error_marker') and
> %% `{warning, ...}' (type `warning_marker'),
> %% which only contain the associated line number *of the
> %% error descriptor*; this is all handled transparently
> %% by `get_pos' and `set_pos'.
>
> get_pos(#tree{attr = Attr}) ->
> Attr#attr.pos;
> get_pos(#wrapper{attr = Attr}) ->
> Attr#attr.pos;
> get_pos({error, {Pos, _, _}}) ->
> Pos;
> get_pos({warning, {Pos, _, _}}) ->
> Pos;
> get_pos(Node) ->
> %% Here, we assume that we have an `erl_parse' node
> %% with position information in element 2.
> element(2, Node).
>
> set_pos(Node, Pos) ->
> case Node of
> #tree{attr = Attr} ->
> Node#tree{attr = Attr#attr{pos = Pos}};
> #wrapper{attr = Attr} ->
> Node#wrapper{attr = Attr#attr{pos = Pos}};
> _ ->
> %% We then assume we have an `erl_parse' node,
> %% and create a wrapper around it to make
> %% things more uniform.
> set_pos(wrap(Node), Pos)
> end.
>
> The type here is a little vague. The additional tuples appear
> to be {error,{Pos,_,_}}, {warning,{Pos,_,_}}, and the
> {Tag,Pos...} tuples returned by erl_parse. The thing here is
> that there are five different cases. For some purposes,
> it would be better to write
>
> -discontiguous([get_pos/1,set_pos/2]).
>
> get_pos(#tree{attr = Attr}) -> Attr#attr.pos.
> set_pos(#tree{attr = Attr} = Node, Pos) ->
> Node#tree{attr = Attr#attr{pos = Pos}}.
>
> get_pos(#wrapper{attr = Attr}) -> Attr#attr.pos.
> set_pos(#wrapper{attr = Attr} = Node, Pos) ->
> Node#wrapper{attr = Attr#attr{pos = Pos}}.
>
> get_pos({error, {Pos,_,_}}) -> Pos.
> % What should set_pos/2 do in this case?
>
> get_pos({warning, {Pos,_,_}}) -> Pos.
> % What should set_pos/2 do in this case?
>
> get_pos(Node) -> element(2, Node). % assume erl_parse node
> set_pos(Node, Pos) -> % assume erl_parse node
> set_pos(wrap(Node), Pos). % wrap it for uniformity
>
> This brings out the parallel between the two functions,
> and the way the parallel fails, more clearly than any other
> possible layout. It nags at you to either finish the
> parallel with the obvious
>
> set_pos({error, {_,X,Y}}, Pos) ->
> {error, {Pos,X,Y}}.
> and
> set_pos({warning, {_,X,Y}), Pos) ->
> {warning, {Pos,X,Y}}.
>
> clauses or to at least change the comments to
>
> % set_pos/2 falls through to the last case.
>
> comments.
>
> We have the same pattern, without the failure of parallelism,
> in two more functions from that file:
>
> get_com(#tree{attr = Attr}) -> Attr#attr.com;
> get_com(#wrapper{attr = Attr}) -> Attr#attr.com;
> get_com(_) -> none.
>
> set_com(Node, Com) ->
> case Node of
> #tree{attr = Attr} ->
> Node#tree{attr = Attr#attr{com = Com}};
> #wrapper{attr = Attr} ->
> Node#wrapper{attr = Attr#attr{com = Com}};
> _ ->
> set_com(wrap(Node), Com)
> end.
>
> These could be
>
> -discontiguous([get_com/1,set_com/1]).
>
> get_com(#tree{attr = Attr}) -> Attr#attr.com.
> set_com(#tree{attr = Attr} = Node, Com) ->
> Node#tree{attr = Attr#attr{com = Com}}.
>
> get_com(#wrapper{attr = Attr}) -> Attr#attr.com.
> set_com(#wrapper{attr = Attr} = Node, Com) ->
> Node#wrapper{attr = Attr#attr{com = Com}}.
>
> get_com(_) -> none. % error, warning, erl_parse.
> set_com(Node, Com) ->
> set_com(wrap(Node), Com).
>
> Well, once again the parallel is not quite perfect.
> The documentation for wrap/1 says that it assumes
> its argument is a class erl_parse tuple, which here
> means that it appears that it should NOT be an error
> or warning.
>
> The point of interest here is that just looking at the
> existing functions didn't ring any alarms; it was not
> until I said "these seem to be about the same data
> structure; I wonder if interleaving can make the
> connection clearer and make it easier to ensure that
> getters and setters are properly related?" that my
> attention was properly drawn to the differences.
>
> It's particularly interesting that the very first Erlang/OTP
> source file I looked at provided examples.
> The third is like the second, but relates to code
> written by a computer, not a human. For example, if
> generating a functional representation of some sort
> of state machine, it can be convenient to organise
> the output around the states, but the present scheme
> requires it to be organised around the functions that
> deal with the states.
>
>
>
> Rationale
>
> Prolog systems have supported a :- discontiguous declaration
> for 20+ years. The approach is a proven one. It is a simple
> generalisation of the language which can be hidden from all
> "downstream" tools. Only tools that try to deal with Erlang
> syntax without fully parsing it could notice the difference,
> and they should largely ignore it.
>
>
>
>
> Backwards Compatibility
>
> All existing Erlang code remains acceptable with unchanged
> semantics. Existing language-processing tools are unaffected
> if they rely on erl_parse.
>
>
>
> Reference Implementation
>
> None in this draft.
>
>
>
> References
>
> None.
>
>
>
> Copyright
>
> This document has been placed in the public domain.
>
>
>
> Local Variables:
> mode: indented-text
> indent-tabs-mode: nil
> sentence-end-double-space: t
> fill-column: 70
> coding: utf-8
> End:
> _______________________________________________
> eeps mailing list
> eeps@REDACTED
> http://erlang.org/mailman/listinfo/eeps
--
/ Raimo Niskanen, Erlang/OTP, Ericsson AB
More information about the eeps
mailing list