Should erlang have macro FUNCTION_ARGS ?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Should erlang have macro FUNCTION_ARGS ?

Zhongzheng Liu
Hi mail-list:

We have FUNCTION_NAME and FUNCTION_ARITY in OTP 19+.

Is there FUNCTION_ARGS to get the argument list in current functions?

For example:

     a_function(X, Y) ->
       ?FUNCTION_ARGS.

After preprocessing, the example will look like:

    a_function(X, Y) ->
        [X, Y].

Using this macro, we can use erlang:apply(fun
?FUNCTION_NAME/?FUNCTION_ARITY,  ?FUNCTION_ARGS) to make any function
recursively.

For example:
      -define(RECURSIVE_FUNCION, erlang:apply(fun
?FUNCTION_NAME/?FUNCTION_ARITY,  ?FUNCTION_ARGS)).

      b_function(A) ->
             do_something(),
             ?RECURSIVE_FUNCION.

After preprocessing, the example will look like:

      b_function(A) ->
             do_something(),
             erlang:apply(fun b_function/1, [A]).

Using this macro, we can use io:format("~p", [FUNCTION_ARGS]) to print
arguments in any function.

For example:

      -define(PRINT_ARGS, io:format("~p", [FUNCTION_ARGS])).

      c_function(A) ->
             PRINT_ARGS,
             do_something(A).


After preprocessing, the example will look like:

      b_function(A) ->
             io:format("~p", [A]),
             erlang:apply(fun b_function/1, [A]).
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Should erlang have macro FUNCTION_ARGS ?

Richard A. O'Keefe-2

> On 7/08/2017, at 1:41 PM, Zhongzheng Liu <[hidden email]> wrote:
>
> Hi mail-list:
>
> We have FUNCTION_NAME and FUNCTION_ARITY in OTP 19+.
>
> Is there FUNCTION_ARGS to get the argument list in current functions?

What is "THE argument list"?

Suppose I have
  foo(X, [a,b,c], 42) -> ...
  foo(0, Y, 127) -> ...

which clause defines *THE* argument list?
>
> Using this macro, we can use erlang:apply(fun
> ?FUNCTION_NAME/?FUNCTION_ARITY,  ?FUNCTION_ARGS) to make any function
> recursively.

Unfortunately, the only kind of recursion you can create
this way is the kind you don't want.  Since any variables
there might happen to be in the arguments cannot have changed,
the new call has *exactly* the same arguments as the old, and
will do *exactly* the same as the original call, including the
recursive call.

> After preprocessing, the example will look like:
>
>      b_function(A) ->
>             do_something(),
>             erlang:apply(fun b_function/1, [A]).

This is a non-terminating function, for example.

>
> Using this macro, we can use io:format("~p", [FUNCTION_ARGS]) to print
> arguments in any function.

True.  Considering that arguments can be extremely large,
just how often do we want to print all the arguments unselectively?

I don't think this *CAN* work in the presence of maps.
In a pattern (like the argument list), you have to write
#{ key1 := val1, ..., keyn := valn }
but that syntax is not allowed as an expression.  You have
to write
#{ key1 => val1, ..., keyn => valn }
for that.  For example:

    d_function(#{ a => X }) ->    % syntax error here
       e_function(#{a => X});     % ok
    d_function(#{ b := Y }) ->    % ok
       e_function(#{b := Y}).     % syntax error here

I am not thrilled about this discrepancy.  No other language
I know does this, and it means that I can define a macro
-define(MAGIC_VALUE, ...any ground term...).
that stands for a ground term, and I can use that macro
freely in patterns AND expressions,

  EXCEPT IF IT CONTAINS A MAP.

But that is the way it is, like it or not.


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Should erlang have macro FUNCTION_ARGS ?

Zhongzheng Liu
In reply to this post by Zhongzheng Liu
Hi Richard:

> What is "THE argument list"?
> Suppose I have
>   foo(X, [a,b,c], 42) -> ...
>   foo(0, Y, 127) -> ...
> which clause defines *THE* argument list?

The argument list will change its value in different clause, just like ?LINE.

> >
> > Using this macro, we can use io:format("~p", [FUNCTION_ARGS]) to print
> > arguments in any function.
> True.  Considering that arguments can be extremely large,
> just how often do we want to print all the arguments unselectively?

Using io:format/2 to print arguments is just a example to explain the usage.
In practice I can send arguments to tx(https://github.com/kvakvs/tx)
or store them in somewhere for further analysis.

> I don't think this *CAN* work in the presence of maps.
> In a pattern (like the argument list), you have to write
> #{ key1 := val1, ..., keyn := valn }
> but that syntax is not allowed as an expression.  You have
> to write
> #{ key1 => val1, ..., keyn => valn }
> for that.  For example:
>     d_function(#{ a => X }) ->    % syntax error here
>        e_function(#{a => X});     % ok
>     d_function(#{ b := Y }) ->    % ok
>        e_function(#{b := Y}).     % syntax error here
> I am not thrilled about this discrepancy.  No other language
> I know does this, and it means that I can define a macro
> -define(MAGIC_VALUE, ...any ground term...).
> that stands for a ground term, and I can use that macro
> freely in patterns AND expressions,
>   EXCEPT IF IT CONTAINS A MAP.
> But that is the way it is, like it or not.

I think it can work with temporary variable.

     foo(X, [a,b,c], 42) ->
            ?FUNCTION_ARGS.

will become:

     foo(X=__TEMP_1__,  [a,b,c]=__TEMP_2__,  #{ b := Y }=__TEMP_3__) ->
            [__TEMP_1__, __TEMP_2__, __TEMP_3__] .

It will work with maps.
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Should erlang have macro FUNCTION_ARGS ?

Richard A. O'Keefe-2


On 7/08/17 8:22 PM, Zhongzheng Liu wrote:

>> I don't think this *CAN* work in the presence of maps.

> I think it can work with temporary variable.
>
>      foo(X, [a,b,c], 42) ->
>             ?FUNCTION_ARGS.
>
> will become:
>
>      foo(X=__TEMP_1__,  [a,b,c]=__TEMP_2__,  #{ b := Y }=__TEMP_3__) ->
>             [__TEMP_1__, __TEMP_2__, __TEMP_3__] .
>
> It will work with maps.

OK, but now you are asking for something other than a macro.
One key thing about a macro is that expanding a macro
invocation has no effect whatsoever on the token sequence
outside that invocation.

It seems to me that if you really want this feature,
you should use the machinery that already exists for
the purpose.  That is, you should write a parse
transform.  Parse transforms can pretty much rewrite
anything to anything, and you don't have to wait for
anyone else to change the Erlang system, you can just
plug in your own parse transform any time you want.


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions