Skip to content

Instantly share code, notes, and snippets.

@mjstrasser
Created March 19, 2017 01:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjstrasser/440cbcf7294e1ca0718cfc8ab897d97f to your computer and use it in GitHub Desktop.
Save mjstrasser/440cbcf7294e1ca0718cfc8ab897d97f to your computer and use it in GitHub Desktop.
Higher-order functions in practice from Functional Programming in Erlang MOOC
-module(zipper).
-compile(compile_all).
-include_lib("eunit/include/eunit.hrl").
%% Tail-recursive implementation of zip/2
%% that combines items into 2-tuples.
zip(Xs, Ys) -> lists:reverse(zip(Xs, Ys, [])).
% Stop when either list finishes.
zip([], _, Zs) -> Zs;
zip(_, [], Zs) -> Zs;
zip([X|Xs], [Y|Ys], Zs) ->
zip(Xs, Ys, [{X,Y} | Zs]).
% Simple tests.
zip_test() ->
?assertEqual([], zip([], [3,4])),
?assertEqual([], zip([1,2], [])),
?assertEqual([{1,3},{2,4}], zip([1,2],[3,4])).
%% Tail-recursive implementation of zip_with/3.
zip_with(F, Xs, Ys) ->
lists:reverse(zip_with(F, Xs, Ys, [])).
% Stop when either list finishes.
zip_with(_, _, [], Zs) -> Zs;
zip_with(_, [], _, Zs) -> Zs;
zip_with(F, [X|Xs], [Y|Ys], Zs) ->
zip_with(F, Xs, Ys, [F(X,Y) | Zs]).
% Simple tests.
tup2(X,Y) -> {X,Y}.
sum(X,Y) -> X+Y.
zip_with_test() ->
?assertEqual([{1,3},{2,4}], zip_with(fun tup2/2, [1,2], [3,4])),
?assertEqual([4,6], zip_with(fun sum/2, [1,2], [3,4])).
%% Implement zip/2 using zip_with/3.
zip2(Xs, Ys) -> zip_with(fun (X,Y) -> {X,Y} end, Xs, Ys).
% One test.
zip2_test() ->
?assertEqual([{1,3},{2,4}], zip2([1,2],[3,4])).
% Implement zip_with/3 using zip/2 and lists:map
zip_with2(F, Xs, Ys) ->
Fun = fun({X,Y}) -> F(X,Y) end,
Zipped = zip(Xs, Ys),
lists:map(Fun, Zipped).
% Tests.
zip_with2_test() ->
?assertEqual([], zip_with2(fun tup2/2, [], [3,4])),
?assertEqual([{1,3},{2,4}], zip_with2(fun tup2/2, [1,2], [3,4])),
?assertEqual([4,6], zip_with2(fun sum/2, [1,2], [3,4])).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment