Functional One-Liners in Julia
By: Erik Engheim
Tags: Julialang, One Line, Functional Programming, Programming

Functional One-Liners in Julia

Being such an expressive language, it is easy when programming Julia to start thinking:

Isn’t there an even more conscience and elegant way of solving this problem?

A lot of problems can be solved straightforward with approaches you are used to from other languages. However in Julia there is often an even shorter and clearer way to do things.

Partial Application

Partial application of a function or currying is something that was popularized by Haskell. It means by not providing all the arguments you can return a new function taking the rest of the arguments.

This may sound confusing, so let me give some examples. Normally you would do a comparison like this:

julia> 3 < 4

true

Which is identical to this, because almost everything in Julia is a function:

julia> <(3, 4)

true

What happens if you don’t provide all the arguments?

julia> <(4)

(::Base.Fix2{typeof(<),Int64}) (generic function with 1 method)

What you get instead is a callable object. We can store this, and use it later:

julia> f = <(4);



julia> f(3)

true

How is this useful? It makes is really elegant to work with functions such as map , filter and reduce .

Find all Elements Which are Less Than Value

Find elements in a list or range which are less than a given value. julia> filter(<(5), 1:10) 4-element Array{Int64,1}: 1 2 3 4

You could also use it to find larger values instead:

julia> filter(>(5), 1:10)

5-element Array{Int64,1}:

6

7

8

9

10

Find Index of an Element

We can find the index of every occurrence of the number 4 e.g.

julia> findall(==(4), [4, 8, 4, 2, 1, 5])

2-element Array{Int64,1}:

1

3

Or we can just look for the first occurrence:

julia> findfirst(==(4), [4, 8, 4, 2, 1, 5])

1

This of course works equally well with strings:

julia> findlast(==("foo"), ["bar", "foo", "qux", "foo"])

4

Filter Out Particular File Types

Say you want to get a list of all the .png files in the current directory. How do you do that?

We can use the endswith function.

julia> endswith("somefile.png", ".png")

true

Like many other functions it can be used in partial application which makes it handy to use in filters:

pngs = filter(endswith(".png"), readdir())

Predicate Function Negation

This is a trick I sadly discovered quite late. But it turns out that you can place ! in front of a function to produce a new function which inverts its output. This is actually not built into the Julia language but just a function itself defined as:

!(f::Function) = (x...)->!f(x...)

Again it may not be entirely clear what I am getting at, so let us look at some examples.

Removing Empty Lines

Say you read all the lines in a file given by filename and you want to strip out the empty lines, you could do that like this:

filter(line -> !isempty(line), readlines(filename))

But these is a more elegant approach using partial application of ! :

filter(!isempty, readlines(filename))

Here is an example of using it on the REPL with some dummy data:

julia> filter(!isempty, ["foo", "", "bar", ""])

2-element Array{String,1}:

"foo"

"bar"

Broadcast and Map

Julia has the broadcast function which you can think of as a fancy version of map. You can even use it in similar fashion:

julia> map(sqrt, [9, 16, 25])

3-element Array{Float64,1}:

3.0

4.0

5.0



julia> broadcast(sqrt, [9, 16, 25])

3-element Array{Float64,1}:

3.0

4.0

5.0

The real power comes when dealing with functions taking multiple arguments and you want one of the arguments to be reused and the others to be changed.

Converting a List of Strings to Numbers

To convert say a string to a number you use the parse function like this:

julia> parse(Int, "42")

42

The naive way to apply this to multiple text strings would be to write:

julia> map(s -> parse(Int, s), ["7", "42", "1331"])

3-element Array{Int64,1}:

7

42

1331

We can simplify this with the broadcast function:

julia> broadcast(parse, Int, ["7", "42", "1331"])

3-element Array{Int64,1}:

7

42

1331

In fact this is so useful and common to do in Julia, that there is an even shorter version using the dot . suffix:

julia> parse.(Int, ["7", "42", "1331"])

3-element Array{Int64,1}:

7

42

1331

You can even chain this:

julia> sqrt.(parse.(Int, ["9", "16", "25"]))

3-element Array{Float64,1}:

3.0

4.0

5.0

Convert Snake Case to Camel Case

In programming we often have identifiers written like hello_how_are_you which we may want to covert to camel case written like HelloHowAreYou . Turns out you can do this easily with just one line of code in Julia.