DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. Languages
  4. Erlang: higher order functions

Erlang: higher order functions

Giorgio Sironi user avatar by
Giorgio Sironi
·
Jan. 09, 13 · Interview
Like (0)
Save
Tweet
Share
5.63K Views

Join the DZone community and get the full member experience.

Join For Free

Erlang is a functional language: it discourage assignments and implements immutability of variables, plus providing the classic set of higher-order functions that these languages are famous for.

Anonymous functions

Of course functions in Erlang are not limited to named functions definition. It's esy to create functions on the fly, inside other code.

These functions can be used right away:

anonymous_function_test() ->
  Squared = (fun(N) -> N*N end)(5),
  ?assertEqual(25, Squared).

or they can be assigned to variables as any other value:

assigned_anonymous_function_test() ->
  Square = fun(N) -> N*N end,
  Squared = Square(5),
  ?assertEqual(25, Squared).

The ability to generate functions is key in implementing logic: an object can be think of as a set of correlated functions, generated over the same data. These functions, referring to already existing variables, are called closures (oversimplified definition, sorry).

To build closures, you can refer freely to variables inside the current scope. Being the variables immutable, you don't have to worry about concurrent modifications or actions at a distance.

closure_currying_test() ->
  Times = fun(M) -> fun(N) -> M * N end end,
  FiveTimes = Times(5),
  ?assertEqual(15, FiveTimes(3)).

The higher-order functions

Higher-order functions are functions that takes as arguments other functions: if you had already wrote 10 lines of code in a functional language, you'll know a few of them. And if you did not live under a rock, you'll know at list map and reduce.

Let's define some functions of the zeroth-order. Named functions and anonymous functions can be interchanged in all the examples that follow.

For a named function, simply pass to the higher-order function the keyword fun followed by the name and the arity of the function:

fun square/1

For an anonymous function, simply use the variable name:

Square

For simplicity I will stay with named functions:

square(N) -> N * N.

is_square(N) ->
  Root = erlang:round(math:sqrt(N)),
  Root * Root == N.

We can use these named functions as if they were kept into variables, with the right name. Map applies a function to each element of a list, returning a new list with the results:

map_test() ->
  ?assertEqual([1, 4, 9], lists:map(fun square/1, [1, 2, 3])).

Filter is also a famous example of higher-order functions: it selects the element of a list that satisfy a predicate.

filter_test() ->
  ?assertEqual([4], lists:filter(fun is_square/1, [3, 4, 5])).

A predicate is defined as a function of a single value, which is an element of a list, and that return a boolean.

There are other two functions that take a predicate as an argument, besides the list to work on. all/2 and any/2 return a boolean:

all_test() ->
  ?assertEqual(true, lists:all(fun is_square/1, [4, 9])),
  ?assertEqual(false, lists:all(fun is_square/1, [3, 4, 9])).

any_test() ->
  ?assertEqual(true, lists:any(fun is_square/1, [3, 4, 5])),
  ?assertEqual(false, lists:any(fun is_square/1, [3, 5, 7])).

Advanced primitives

Which is almost an oxymoron. However, there are more complex constructs too, that you will be glad are already implemented when needing them. Higher-order functions have great reusability:

dropwhile_test() ->
  ?assertEqual([5, 6], lists:dropwhile(fun is_square/1, [1, 4, 5, 6])).

takewhile_test() ->
  ?assertEqual([1, 4], lists:takewhile(fun is_square/1, [1, 4, 5, 6])).

dropwhile/2 and takewhile/2 walk a list and, respectively, remove or keep the elements satisfying the predicate to produce a new list. Remember, immutability means all these functions always return their result and cannot touch the state of what you pass to them.

Fold (also known as reduce) comes in the foldl/3 (from the left) and foldr/3 (from the right) variants. Its job is to recursively apply a function to pair of elements from a list, starting with a seed (accumulator) that is passed to it and is usually the neutral element for the function.

foldl_test() ->
  Sum(A, B) -> A + B end,
  ?assertEqual(10, lists:foldl(Sum, 0, [1, 2, 3, 4])).

Explore more of these functions  in the Erlang documentation.

Conclusions

Higher-order functions are the bread and butter of functional languages, although they are one of the simpler aspects of it and not the whole picture. Knowing how to use map and foldl is general Erlang knowledge, but we'll see in the next article that there are even more idiomatic ways to work with lists: list comprehensions.

Erlang (programming language)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Java Concurrency: LockSupport
  • What Are the Different Types of API Testing?
  • gRPC on the Client Side
  • OpenVPN With Radius and Multi-Factor Authentication

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: