user3355020
user3355020

Reputation: 325

How to invoke Erlang function with variable?

4> abs(1).
1
5> X = abs.
abs
6> X(1).
** exception error: bad function abs
7> erlang:X(1).
1
8>

Is there any particular reason why I have to use the module name when I invoke a function with a variable? This isn't going to work for me because, well, for one thing it is just way too much syntactic garbage and makes my eyes bleed. For another thing, I plan on invoking functions out of a list, something like (off the top of my head):

[X(1) || X <- [abs, f1, f2, f3...]].

Attempting to tack on various module names here is going to make the verbosity go through the roof, when the whole point of what I am doing is to reduce verbosity.

EDIT: Look here: http://www.erlangpatterns.org/chain.html The guy has made some pipe-forward function. He is invoking functions the same way I want to above, but his code doesn't work when I try to use it. But from what I know, the guy is an experienced Erlang programmer - I saw him give some keynote or whatever at a conference (well I saw it online).

Did this kind of thing used to work but not anymore? Surely there is a way I can do what I want - invoke these functions without all the verbosity and boilerplate.

EDIT: If I am reading the documentation right, it seems to imply that my example at the top should work (section 8.6) http://erlang.org/doc/reference_manual/expressions.html

Upvotes: 3

Views: 1322

Answers (3)

Sylvain Leroux
Sylvain Leroux

Reputation: 52040

I know abs is an atom, not a function. [...] Why does it work when the module name is used?

The documentation explains that (slightly reorganized):

ExprM:ExprF(Expr1,...,ExprN)

each of ExprM and ExprF must be an atom or an expression that evaluates to an atom. The function is said to be called by using the fully qualified function name.

ExprF(Expr1,...,ExprN)

ExprF must be an atom or evaluate to a fun. If ExprF is an atom the function is said to be called by using the implicitly qualified function name.

  • When using fully qualified function names, Erlang expects atoms or expression that evaluates to atoms. In other words, you have to bind X to an atom: X = atom. That's exactly what you provide.
  • But in the second form, Erlang expects either an atom or an expression that evaluates to a function. Notice that last word. In other words, if you do not use fully qualified function name, you have to bind X to a function: X = fun module:function/arity.

Upvotes: 7

nu-ex
nu-ex

Reputation: 681

Try:

X = fun(Number) -> abs(Number) end.

Updated:

After looking at the discussion more, it seems like you're wanting to apply multiple functions to some input.

There are two projects that I haven't used personally, but I've starred on Github that may be what you're looking for.

Both of these projects use parse transforms:

Pipeline is unique because it uses a special syntax:

Result = [fun1, mod2:fun2, fun3] (Arg1, Arg2).

Of course, it could also be possible to write your own function to do this using a list of {module, function} tuples and applying the function to the previous output until you get the result.

Upvotes: 1

user4651282
user4651282

Reputation:

In the expression X=abs, abs is not a function but an atom. If you want thus to define a function,you can do so:

D = fun erlang:abs/1.

or so:

X = fun(X)->abs(X) end.

Upvotes: 8

Related Questions