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