Is there a better way to write Head and Tail without using fun?

Viewed 77
f6(List) ->
     
          [Head2 | Tail2 ] <- [List],
          Head2.
          Tail2.

Hello there I have been trying to figure out the way to use Head and Tail without using fun and for the shell we can just assign the head and tail as [H|T] = A. But for the editor I have absolutely no idea as i am just learning. any help will be appreciated. I just need to know how a simple adding the number in a list with H & T looks like.

Sample Input : [1,2,3] or any three numbers and the output will be something like 6 the total number. I'm stuck where I can just assign a list to head and tail.

Pardon for the wrong format if any and Thanks in advance.

2 Answers

A couple of immediate problems:

<- is used in list comprehensions. See https://www.erlang.org/doc/programming_examples/list_comprehensions.html or https://learnyousomeerlang.com/starting-out-for-real#list-comprehensions.

Assignment (matching, actually) works the same in a module:

    [H | T] = L,
    % ...do something with H and T...

Next:

[Head2 | Tail2 ] <- [List],

This isn't doing what you want either, even if we fix the <-. You've wrapped your list in another list, so if you started with List = [1, 2, 3], you'll actually be doing [Head2 | Tail2] = [[1, 2, 3]], and you'll end up with Head2 = [1, 2, 3] and Tail2 = [].


Outside the shell, you must put your Erlang code in a module, so you'll end up with something like this (the module name must match the filename, so my_module.erl):

-module(my_module).

% ...

In your example code, I've corrected the above two problems, which leaves us with:

f6(List) ->
          [Head2 | Tail2 ] = List,
          Head2.
          Tail2.

This still won't work, because the dot (.) means the end of a function. So that Tail2. is just hanging around, causing a syntax error.

If you want to sum three numbers in a list, the simplest option is this:

-module(my_module).

f6([A, B, C]) ->
   A + B + C.

This uses matching in the function header. It requires a three-element list, and it matches it such that each of A, B and C takes one of the elements. You can then add them.

It's not very flexible. What you probably wanted was recursion:

% don't do this, though; read on.
sum([H | T]) ->
    H + sum(T);
sum([]) ->
    0.

But that's going to blow the stack, because it's not tail-recursive. What you actually want is this:

sum(List) ->
    sum(List, 0).

sum([], Acc) ->
    Result;
sum([Elt | Rest], Acc) ->
    sum(Rest, Acc + Elt).

This uses an accumulator with tail-recursion to add the values in the list.

This could be re-written as follows (taken directly from the docs at https://www.erlang.org/doc/man/lists.html#foldl-3:

sum(List) -> lists:foldl(fun(X, Sum) -> X + Sum end, 0, List).

But, if you really wanted the short version, there's already lists:sum(List). See https://www.erlang.org/doc/man/lists.html#sum-1

I have been trying to figure out the way to use Head and Tail without using fun and for the shell we can just assign the head and tail as [H|T] = A. But for the editor I have absolutely no idea...

In the shell:

~/erlang_programs$ erl
Erlang/OTP 24 [erts-12.0.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]

Eshell V12.0.2  (abort with ^G)
1> List = [dog, 20, 30].
[dog,20,30]

2> [H|T] = List.
[dog,20,30]
3> io:format("Head = ~w~n", [H]).
Head = dog
ok

4> io:format("Tail = ~w~n", [T]).
Tail = [20,30]
ok

Here's an idea:

-module(a).
-export([f1/1]).

f1(List) ->   %% or you could write it as f([H|T]) -> 
    [H|T] = List,
    io:format("Head = ~w~n", [H]),
    io:format("Tail = ~w~n", [T]).

Using the module in the shell:

~/erlang_programs$ erl
Erlang/OTP 24 [erts-12.0.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]

Eshell V12.0.2  (abort with ^G)

1> c(a).
{ok,a}

2> List = [dog, 20, 30].
[dog,20,30]

3> a:f1(List).
Head = dog
Tail = [20,30]
ok

Pretty much identical.

I just need to know how a simple adding the number in a list with H & T looks like.

Here's the trick you need:

-module(a).
-export([sum_it/1]).

sum_it(List) ->
    StartTotal = 0,
    sum_it(List, StartTotal).

sum_it([H|T], Total) -> 
    CurrentTotal = Total + H,
    sum_it(T, CurrentTotal);
sum_it([], Total) ->
    Total.

You define a function sum_it/1 that does nothing but accept the argument, then calls another function to do the work: sum_it/2. Defining a second function, which can have the same name (because it has a different number of arguments) or a different name, allows you to pass an extra argument for the accumulator. Because erlang doesn't have global variables to store the results in, you can add an accumulator variable to the function parameter variables to store the results in.

In the case of the sum_it/2 function definition, you have the function parameter variable [H|T] to match a list, which contains the numbers you want to sum, and you add the accumulator variable Total to store the results.

Related