4

I am playing around with example code from Programming with Erlang. I am struck with funs. help me understand whats going wrong with below code.

-export([totalcost/1]).

Costeach = fun(X) -> {W,Q} = X, shop:cost(W)*Q end.
sum(H|T) -> H + sum[T];
sum([]) -> 0.
totalcost(L) -> sum(lists:map(Costeach,L)).

All i wanted to achieve was being able to pass Variable (with fun assigned to it) as parameter to map. get total cost from this module

i keep getting syntax error/ Costeach not initialized error.

Mahantesh
  • 79
  • 8

1 Answers1

6

You cannot define a function like that at the top level. You have two options: use the syntax you're using but declare it inside a named function, or declare it like a named function and use fun name/arity syntax to convert it to an anonymous function to pass into lists:map.

First approach:

sum(H|T) -> H + sum[T];
sum([]) -> 0.
totalcost(L) ->
  Costeach = fun(X) -> {W,Q} = X, shop:cost(W)*Q end.
  sum(lists:map(Costeach,L)).

Second approach:

costeach(X) -> {W,Q} = X, shop:cost(W)*Q.
sum(H|T) -> H + sum[T];
sum([]) -> 0.
totalcost(L) -> sum(lists:map(fun costeach/1,L)).

Tip: you can do the destructure in the function arguments in both cases to save a line of code:

Costeach = fun({W,Q}) -> shop:cost(W)*Q end.

or

costeach({W, Q}) -> shop:cost(W)*Q.
Dogbert
  • 212,659
  • 41
  • 396
  • 397
  • Or the best `totalcost(L) -> lists:sum([shop:cost(W)*Q || {W,Q} <- L]).` – Hynek -Pichi- Vychodil Aug 21 '17 at 10:44
  • 2
    @Hynek-Pichi-Vychodil That's more concise, but there's a very important difference that's easy to miss and isn't explicit in [the documentation](http://erlang.org/doc/programming_examples/list_comprehensions.html), which is that the comprehension filters out non-matching elements, while the function clause will crash. – Ryan Stewart Aug 21 '17 at 13:25
  • @RyanStewart: I know it of course but there is not specified in question if an error is the desired behavior. – Hynek -Pichi- Vychodil Aug 22 '17 at 15:17
  • @Dogberts answer1 helped , i wanted to understand if variable with anonymous fun assigned can be used across named functions by defining and binding it at top level. So anonymous fun needs to be assigned to variable within named function . how ever i had to change some syntax. `-module(new1).` `-export([total/1]).` `sum([H|T]) -> H + sum(T);` `sum([])->0.` `total(L)-> ` `Costeach = fun(X) -> {W,Q}=X, shop:cost(W)*Q end,` `sum(lists:map(Costeach,L)).` – Mahantesh Aug 23 '17 at 08:43
  • https://stackoverflow.com/questions/867418/how-do-you-write-a-fun-thats-recursive-in-erlang is also helpful – Mahantesh Aug 26 '17 at 05:05