4

I am just starting Erlang (though with some lisp background) and have a question about pattern matching on lists.

If I say

[Head | Tail] = [1, 2, 3].

then I get

Head = 1
Tail = [2, 3]

If I want to do the same from the other end without reversing the list twice, is there some succint patter for that? I would like to be able to say something like:

[All_but | last] = [1, 2, 3].

and get:

All_but = [1, 2]
last = 3

Thanks.

PS: I know my example is incorrect behavior.

asb
  • 4,392
  • 1
  • 20
  • 30
  • 1
    It might be enlightening to ask yourself why the answer is "no" in lisp (not that Erlang and quite a few lisp implementations don't have some shortcuts built in). What does a chain of conses look like? Why does everyone avoid foldr? etc. – zxq9 Feb 17 '15 at 18:41
  • I understand and agree. Very good point. From a purely recursive point of view however, recursing from the tail or the head are both desirable. So, was just being wishful, I guess. – asb Feb 17 '15 at 18:45
  • "Purely recursive", sure, but not "tail recursive", which is really the point in a functional language and the place where the difference between an array and a lisp-style list of conses comes into play. Somewhat related discussion http://stackoverflow.com/questions/27459561/erlang-sublist-function-performance/27459972#27459972 – zxq9 Feb 17 '15 at 18:49
  • Thanks for pointing out the other discussion. Definitely useful. – asb Feb 17 '15 at 18:53

1 Answers1

3

There is no succinct pattern for that. You can use the functions lists:last and lists:droplast, which walk the entire list to find the tail:

> lists:last([1,2,3]).
3
> lists:droplast([1,2,3]).
[1,2]

If you'll be doing this with long lists, you'll probably want to write a function that traverses the list only once but returns both the new list and the last element. The source code for lists:last and lists:droplast could serve as inspiration.

legoscia
  • 39,593
  • 22
  • 116
  • 167