Day 19 – Functional Programming with Raku

Functional Programming in Raku

I watched a really nice video recently, Functional Programming in 40 minutes, which I thought was really good. I’ve done bits of functional programming over the years but I know lots of people find the ideas behind it quite confusing.

So the first thing I’d say is go watch that video, it really helps.

I’ll wait.

Back? OK, cool, so I’m sure you’ve got the core concept here functional programming can be broken down into 3 main things.

  • Pure Functions
  • Immutable Data Structures
  • Bridging Systems

So how easy is it to bring these ideas into Raku code? Would it surprise you to know “really really” would be the answer to that question? I didn’t think so, lets go over each section in turn.

Pure Functions

So a pure function causes no side effects. And for any given input it always gives the same output. Raku includes a is pure trait that you can use to flag a code block to say that it will return the same value and the compiler can use this as a hint to replace calls with constants. Generally if you flag a function with is pure you don’t want to cause side effect either (as your code may only be called once).

Not only that Raku has a number of ways to generate code blocks from named subs sub name($n) {"Hello $n"} through anonymous subs sub ($n) {"Hello $n"} on to pointy code blocks -> $n {"Hello $n"} and finally just plain blocks {"Hello $_"}; all of these can be called or assigned to variables and used in other subs.

Raku also allows you to use some more complex function creation techniques function composition and currying; whilst these aren’t related to the video they are kind of cool so I’m going to digress. Bear with me.

Function Composition

Function composition lets us take advantage of the idea that f(g(x)) will always return the same value for a given value of x. And as such we can create a new function h where h(x) == f(g(x)). The composition operator ( or o) lets use define h without having to formally wrap the functions :

my &h = &f ∘ &g; # or my &h = &f o &g;

Now when you call h(x) it’s the same as calling f(g(x)). Function composition lets you create complex chains of functions that you can pass around to other functions easily.

Currying

Currying functions is when you want to take a function and generate a new function made up from partially calling the original…

Ok lets explain. Lets say I’ve got a greeting function that takes a greeting and name like so :

sub greeting( Str $greeting, Str $name ) { 
    return "$greeting $name!" 
}

Ok. Now we’d like a function that only takes a name, the greeting will be set to “Hello”. We could do something like this :

sub hello( Str $name ) {
    greeting( "Hello", $name );
}

Or possibly create a closure.

my &hello = -> $greeting { 
    -> $name { 
        greeting($greeting, $name) 
    }
}("Hello");

But Raku has a built in method for currying a function assuming which simplifies things to this :

my &hello = &greeting.assuming("Hello");

And that’s fine. But what if we want to assume a later value? That’s easy unnamed questioner we can make use of whatever stars like so.

my &greet-sam = &greeting.assuming(*, "Sam");

Now we can call greet-sam("Hi") and get back “Hi Sam!”.

By combining function composition and currying you can create complex functions from simple, easily testable, parts.

Immutable Data Structures

Raku provides us with a number of ways to have Immutable Data including Maps, Lists, Sets and Bags. You can also bind values to variables or create them as unsigiled variables or constants :

my $foo := 10;
my \foobar = 12;
constant bar = 11;

Also by default all Raku Objects are Immutable when you create them the example Point class for instance :

class Point {
	has Num $.x;
	has Num $.y;
}

You can create a Point instance assigning x and y values on creation but once it’s created you can’t modify them. Sure you can create mutable objects with is rw but if you want to do functional programming then you’re all set.

Also when you pass arguments to functions they are also immutable unless you specifically mark them as is rw or is copy. The second of these gives you a new copy you can modify inside your function that doesn’t affect its original.

So Raku provides us with all we need for Immutable data.

Bridging Systems

So if you want to pass information to and from the non functional part of your code what kind of Bridge can you use? There are two obvious answer with slightly different use cases Channels and Supplies.

Supplies can be used when we want to react to something; I’d suggest when an input comes in from the outside and you want your functional system to handle it.
You can setup a react block to take the incoming data (or function and pass it into the code of your functional code). Then when the code is done you can pass the result to a Channel that feeds the data back out to the outside world.

By combining all this together you got access to most of the functionality of a purely functional language but also a powerful object system and concurrency. The best of all worlds.

Published by scimon

Web Developer and some time games designer. Spent 20 years in Scotland now back down South.

One thought on “Day 19 – Functional Programming with Raku

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.