[erlang-questions] Defining static functions in abstract modules

Hynek Vychodil <>
Wed Apr 9 11:37:38 CEST 2008


Still don't understand. Internal helper functions should be internally in
which? From where you want call "foo(X)"? Where you would like to define
"foo(X)"?

On Wed, Apr 9, 2008 at 11:22 AM, Matthew Dempsky <>
wrote:

> Because I want to be able to abstract away how to instantiate a
> module, and I want to be able to define internal helper functions to
> do it, and I want to be able to call them "foo(X)" instead of
> "new(foo, X)".
>
> On Wed, Apr 9, 2008 at 2:20 AM, Hynek Vychodil <>
> wrote:
> > UGH, static functions? Where is benefit to do it? What matter? I don't
> > understand.
> >
> >
> >
> > On Wed, Apr 9, 2008 at 11:04 AM, Matthew Dempsky <>
> > wrote:
> >
> > >
> > >
> > >
> > > It would be nice to be able to define arbitrary static functions
> > > within an abstract module.  Right now you can kludge around this by
> > > exploiting that local functions named 'new' are always static and
> > > write something like
> > >
> > >    new(incr, X) -> X + 1.
> > >
> > > but it would be nicer to just write
> > >
> > >    -static([incr/1]).
> > >    incr(X) -> X + 1.
> > >
> > > Below is a very rudimentary patch that adds support for this syntax.
> > > It's basically only enough to compile and run very simple test cases
> > > and to demonstrate that implementing this does not seem too difficult.
> > > (One problem I'm already aware of is that a static function foo/1 and
> > > an instance function foo/0 silently collide without any warning... so
> > > don't do that. ;-))
> > >
> > > Another option would be to make the attribute statement just
> > > "-static([incr])." and then all incr functions are defined static, but
> > > that seems unnecessarily limiting.
> > >
> > > If the long-term goal is to have separate namespaces for static and
> > > instance functions (e.g., so (Mod:new(...)):module_info() works and
> > > returns something meaningful for the module instance), then maybe a
> > > syntax that actually decorates individual function definitions would
> > > be better?
> > >
> > > Are there any plans on adding static functions in a future release?
> > >
> > >
> > > --- stdlib/src/erl_parse.yrl.orig       2007-11-27 07:57:32.000000000
> > -0800
> > > +++ stdlib/src/erl_parse.yrl    2008-04-09 01:25:31.000000000 -0700
> > > @@ -627,6 +627,12 @@
> > >            {attribute,La,export,farity_list(ExpList)};
> > >        _Other -> error_bad_decl(La, export)
> > >     end;
> > > +build_attribute({atom,La,static}, Val) ->
> > > +    case Val of
> > > +        [ExpList] ->
> > > +            {attribute,La,static,farity_list(ExpList)};
> > > +        _Other -> error_bad_decl(La, static)
> > > +    end;
> > >  build_attribute({atom,La,import}, Val) ->
> > >     case Val of
> > >        [Name] ->
> > > --- compiler/src/sys_pre_expand.erl.orig        2008-02-05
> > 05:37:09.000000000 -0800
> > > +++ compiler/src/sys_pre_expand.erl     2008-04-09 01:26:06.000000000
> > -0700
> > > @@ -38,6 +38,7 @@
> > >                  parameters=undefined,          %Module parameters
> > >                  package="",                    %Module package
> > >                  exports=[],                    %Exports
> > > +                 statics=[],                    %Statics
> > >                  imports=[],                    %Imports
> > >                  mod_imports,                   %Module Imports
> > >                  compile=[],                    %Compile flags
> > > @@ -109,6 +110,7 @@
> > >                 end,
> > >             {Fs1,Xs,Ds} = sys_expand_pmod:forms(Fs0, Ps,
> > >                                                 St0#expand.exports,
> > > +                                                St0#expand.statics,
> > >                                                 St0#expand.defined),
> > >            St1 = St0#expand{exports=Xs, defined=Ds},
> > >            {Fs2,St2} = add_instance(Ps, Fs1, St1),
> > > @@ -220,6 +222,8 @@
> > >               package = packages:strip_last(M)};
> > >  attribute(export, Es, St) ->
> > >     St#expand{exports=union(from_list(Es), St#expand.exports)};
> > > +attribute(static, Ss, St) ->
> > > +    St#expand{statics=union(from_list(Ss), St#expand.statics)};
> > >  attribute(import, Is, St) ->
> > >     import(Is, St);
> > >  attribute(compile, C, St) when is_list(C) ->
> > > --- compiler/src/sys_expand_pmod.erl.orig       2008-02-05
> > 05:38:12.000000000 -0800
> > > +++ compiler/src/sys_expand_pmod.erl    2008-04-09 01:32:36.000000000
> > -0700
> > > @@ -25,18 +25,19 @@
> > >  %% and 'exports'. The automatic 'new/N' function is neither added to
> the
> > >  %% definitions nor to the 'exports'/'defines' lists yet.
> > >
> > > --export([forms/4]).
> > > +-export([forms/5]).
> > >
> > > --record(pmod, {parameters, exports, defined, predef}).
> > > +-record(pmod, {parameters, exports, statics, defined, predef}).
> > >
> > >  %% TODO: more abstract handling of predefined/static functions.
> > >
> > > -forms(Fs0, Ps, Es0, Ds0) ->
> > > +forms(Fs0, Ps, Es0, Ss0, Ds0) ->
> > >     PreDef = [{module_info,0},{module_info,1}],
> > > -    forms(Fs0, Ps, Es0, Ds0, PreDef).
> > > +    forms(Fs0, Ps, Es0, Ss0, Ds0, PreDef).
> > >
> > > -forms(Fs0, Ps, Es0, Ds0, PreDef) ->
> > > -    St0 = #pmod{parameters=Ps,exports=Es0,defined=Ds0,
> predef=PreDef},
> > > +forms(Fs0, Ps, Es0, Ss0, Ds0, PreDef) ->
> > > +    St0 = #pmod{parameters=Ps,exports=Es0,statics=Ss0,defined=Ds0,
> > > +                predef=PreDef},
> > >     {Fs1, St1} = forms(Fs0, St0),
> > >     Es1 = update_function_names(Es0, St1),
> > >     Ds1 = update_function_names(Ds0, St1),
> > > @@ -50,15 +51,22 @@
> > >     [update_function_name(E, St) || E <- Es].
> > >
> > >  update_function_name(E={F,A}, St) when F =/= new ->
> > > -    case ordsets:is_element(E, St#pmod.predef) of
> > > +    case ordsets:is_element(E, St#pmod.predef) orelse
> > > +        ordsets:is_element(E, St#pmod.statics) of
> > >        true -> E;
> > >        false -> {F, A + 1}
> > >     end;
> > >  update_function_name(E, _St) ->
> > >     E.
> > >
> > > -update_forms([{function,L,N,A,Cs}|Fs],St) when N =/= new ->
> > > -    [{function,L,N,A+1,Cs}|update_forms(Fs,St)];
> > > +update_forms([F0={function,L,N,A,Cs}|Fs],St) when N =/= new ->
> > > +    F = case ordsets:is_element({N,A}, St#pmod.statics) of
> > > +            true ->
> > > +                F0;
> > > +            false ->
> > > +                {function,L,N,A+1,Cs}
> > > +        end,
> > > +    [F|update_forms(Fs,St)];
> > >  update_forms([F|Fs],St) ->
> > >     [F|update_forms(Fs,St)];
> > >  update_forms([],_St) ->
> > > @@ -74,9 +82,14 @@
> > >     {[], St0}.
> > >
> > >  %% Only function definitions are of interest here. State is not
> updated.
> > > -form({function,Line,Name0,Arity0,Clauses0},St) when Name0 =/= new ->
> > > -    {Name,Arity,Clauses} = function(Name0, Arity0, Clauses0, St),
> > > -    {{function,Line,Name,Arity,Clauses},St};
> > > +form(F = {function,Line,Name0,Arity0,Clauses0},St) when Name0 =/= new
> ->
> > > +    case ordsets:is_element({Name0, Arity0}, St#pmod.statics) of
> > > +        true ->
> > > +            {F,St};
> > > +        false ->
> > > +            {Name,Arity,Clauses} = function(Name0, Arity0, Clauses0,
> St),
> > > +            {{function,Line,Name,Arity,Clauses},St}
> > > +    end;
> > >  %% Pass anything else through
> > >  form(F,St) -> {F,St}.
> > >
> > > @@ -362,7 +375,13 @@
> > >  expr({call,Lc,{atom,Lf,F},As0},St) ->
> > >     %% Local function call - needs THIS parameter.
> > >     As1 = expr_list(As0,St),
> > > -    {call,Lc,{atom,Lf,F},As1 ++ [{var,0,'THIS'}]};
> > > +    As2 = case ordsets:is_element({F, length(As1)}, St#pmod.statics)
> of
> > > +              true ->
> > > +                  As1;
> > > +              false ->
> > > +                  As1 ++ [{var,0,'THIS'}]
> > > +          end,
> > > +    {call,Lc,{atom,Lf,F},As2};
> > >  expr({call,Line,F0,As0},St) ->
> > >     %% Other function call
> > >     F1 = expr(F0,St),
> > > _______________________________________________
> > > erlang-questions mailing list
> > > 
> > > http://www.erlang.org/mailman/listinfo/erlang-questions
> > >
> >
> >
> >
> > --
> > --Hynek (Pichi) Vychodil
>



-- 
--Hynek (Pichi) Vychodil
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080409/7581cb52/attachment.html>


More information about the erlang-questions mailing list