Skip to content

Instantly share code, notes, and snippets.

@andreburgaud
Created July 4, 2017 02:57
Show Gist options
  • Save andreburgaud/9d81b1e7abb141ecebe47e1b2574da79 to your computer and use it in GitHub Desktop.
Save andreburgaud/9d81b1e7abb141ecebe47e1b2574da79 to your computer and use it in GitHub Desktop.
FutureLearn - Functional Programming in Erlang 3.5 - Higher-order functions in practice
-module(hh).
-export([
doubleAll/1,doubleAllHH/1,
evens/1,evensHH/1,
product/1,productHH/1,
zip/2,zipT/2,zipHH/2,
zip_with/3,zip_withHH/3
]).
-include_lib("eunit/include/eunit.hrl").
%% To execute tests in the Erlang shell:
%% > eunit:test(index, [verbose]).
%% -----------------------------------------------------------------------------
%% Using higher-order functions
%% -----------------------------------------------------------------------------
doubleAll([]) -> [];
doubleAll([X|Xs]) ->
[ 2*X | doubleAll(Xs) ].
%% doubleAll with higher function 'list:map'
doubleAllHH(Xs) -> lists:map(fun(X) -> X*2 end, Xs).
evens([]) -> [];
evens([X|Xs]) when X rem 2 == 0 ->
[X | evens(Xs) ];
evens([_|Xs]) ->
evens(Xs).
%% evens with higher order function 'lists:filter'
evensHH(Xs) -> lists:filter(fun(X) -> X rem 2 =:= 0 end, Xs).
product([]) -> 1;
product([X|Xs]) -> X * product(Xs).
%% product with higher order function 'lists:foldr'
productHH(Xs) -> lists:foldr(fun(X, Acc)-> X*Acc end, 1, Xs).
% zip([1,3,5,7], [2,4]) = [ {1,2}, {3,4} ]
zip(_,[]) -> [];
zip([],_) -> [];
zip([X|Xs],[Y|Ys]) ->
[{X,Y}|zip(Xs,Ys)].
% with TR
zipT(Xs,Ys) -> lists:reverse(zipT(Xs,Ys,[])).
zipT(_,[], Acc) -> Acc;
zipT([],_, Acc) -> Acc;
zipT([X|Xs],[Y|Ys],Acc) ->
zipT(Xs,Ys,[{X,Y}|Acc]).
%% zip_with(fun(X,Y) -> X+Y end, [1,3,5,7], [2,4]) = [ 3, 7 ]
zip_with(_,_,[]) -> [];
zip_with(_,[],_) -> [];
zip_with(F,[X|Xs],[Y|Ys]) ->
[F(X,Y)|zip_with(F,Xs,Ys)].
%% Redfinition of zip_with using zip and lists:map
zip_withHH(F, Xs, Ys) ->
lists:map(F, zip(Xs, Ys)).
%% Redfinition of zip using zip_with/3 (zip_withHH)
zipHH(Xs, Ys) ->
zip_withHH(fun(X) -> X end, Xs, Ys).
%% -----------------------------------------------------------------------------
%% TESTS
%% -----------------------------------------------------------------------------
double_all_test_() ->
[?_assertEqual([2,4,6,8], doubleAll([1,2,3,4])),
?_assertEqual([2,4,6,8], doubleAllHH([1,2,3,4])),
?_assertEqual(doubleAll([1,2,3,4]), doubleAllHH([1,2,3,4]))].
evens_test_() ->
[?_assertEqual([2,4,6,8], evens([1,2,3,4,5,6,7,8])),
?_assertEqual([2,4,6,8], evensHH([1,2,3,4,5,6,7,8])),
?_assertEqual(evens([1,2,3,4,5,6,7,8]), evensHH([1,2,3,4,5,6,7,8]))].
product_test_() ->
[?_assertEqual(6, product([1,2,3])),
?_assertEqual(6, productHH([1,2,3])),
?_assertEqual(product([3,100,450]), productHH([3,100,450]))].
zip_test_() ->
[?_assertEqual([{1,2},{3,4}], zip([1,3,5,7],[2,4])),
?_assertEqual([{1,2},{3,4}], zipT([1,3,5,7],[2,4])),
?_assertEqual([{1,2},{3,4}], zipHH([1,3,5,7],[2,4]))].
zip_with_test_() ->
[?_assertEqual([3,7], zip_with(fun(X,Y) -> X+Y end, [1,3,5,7],[2,4])),
?_assertEqual([3,7], zip_withHH(fun({X,Y}) -> X+Y end, [1,3,5,7],[2,4]))].
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment