Solving the Balanced Brackets task using Perl 6 – Part 3

In my attempt to learn Perl 6, I decided to pick up random tasks from the Rosetta Code website to solve. Please view Part 1 and Part 2 of this post if you haven’t already.

In this part, we will cover how to receive user input from the shell (terminal), and how to create and use a Perl 6 module.

Receiving user input is fairly easy.

my $input = prompt "Enter the string to be checked: ";

Were you expecting something more complex? Sorry! You can just use the prompt function which will first print the supplied argument to standard output (the terminal in most cases), and wait for user input. After the user enters some characters to be checked for balancing, she presses the Enter key. This signifies the end of user input, and the $input variable will now contain the user supplied string. Note that the newline is automatically removed, so you don’t have to use chomp on $input.

In our previous posts we defined the check_balance subroutine which does the actual work of validating the balance of the brackets and returns True or False accordingly. Lets see how we can move this subroutine to a module. Modules are great when you need to organize related code into a single place as well as for code reuse.

If you wish you can read this article of mine on how to Create and use a Perl 6 module, or continue reading.

To create a module, you need to place your subroutine in a separate file. Lets get creative and name this file CheckBalance.pm6. Here’s what it looks like.

module CheckBalance;

sub check_balance(Str $b) is export returns Bool {

    my $num_opens = 0;

    for $b.comb -> $c {

        if $c eq '[' {
            $num_opens++;
        }

        if $c eq ']' {
            $num_opens--;
            if $num_opens < 0 {
                return False;
            }
        }
    }

    return $num_opens == 0;
}

This is the same subroutine we wrote in Part 1, except here notice the is export trait. This tells the module to export the check_balance subroutine into the caller’s namespace automatically.

Now in our script we can use the module.

use CheckBalance;

loop {
    my $input = prompt "Enter the string to be checked: ";
    say check_balance($input) ?? 'OK' !! 'NOT OK';
}

Notice the loop keyword. In Perl 6 the loop keyword is similar to the for loop in C. Except here we create a never ending loop. (You can use Ctrl+C to kill the script).

You can check out all the code on Github. I hope you learned something new in Perl 6. Have fun!

Clearing recent entries from Ardour

I use Ardour exclusively as my DAW (Digital Audio Workstation) on my Debian Linux box. But as my number of sessions increased, the recent entries keep showing up when you need to open an existing session.

I could not find any option within Ardour to clear up the recent entries. Well, config files to the rescue. For Ardour 3, the recent file is located in ~/.config/ardour3/recent. Edit that file to clear off any sessions you don’t want to be reminded of and then restart Ardour.

Solving the Balanced Brackets task using Perl 6 – Part 2

In my attempt to lean Perl 6 I decided to solve some classic programming problems available at the Rosetta Code website. Please view Part 1 of this post if you haven’t already. In this post we will cover how to generate a random string and how to accept command line arguments to our script.

Lets see how to generate a random string of brackets as input. First we need a list. Or an array. The two elements of this array will be the characters [ and ]. Here is how we can create an array in Perl 6.

my @brackets = '[', ']';

Note that we don’t need parentheses as in Perl 5 or some other languages to create this array. If you’re coming from Perl 5 then you must be aware of the handy Data::Dumper module to inspect your data structures. In Perl 6, we can directly use the .perl method on any object to inspect it.

say @brackets.perl;

To create an array of numbers 1 to 5

my @nums = 1, 2, 3, 4, 5;

Perl 6 gives us the angle brackets <> to create a list of words. In Perl 5 this was done using the qw operator which is no longer supported in Perl 6.

my @brackets = <[ ]>;
my @fruits = <Orange Lemon Apple Mango>;

Alright, now we need this array of brackets to be replicated n times. You might be familiar with the x operator in Perl 5, which is also available in Perl 6.

my $str = 'a' x 5;
say $str; # $str = 'aaaaa'

Perl 6 gives us the new expression repetition operator xx. Lets see it in action.

my @fruits = <Apple Orange>;
my @fruits_repeated = @fruits xx 2;
say @fruits_repeated; # prints "Apple Orange Apple Orange"

So lets create an array of 3 opening and closing brackets.

my @brackets = <[ ]> xx 3;

Lets quickly gloss over the fact that Perl 6 has the rand function to help us generate random numbers.

The fun part of dealing with arrays is the pick method. The pick method when called on an array will select a random element from the array. An argument supplied to pick indicates how many elements you want to be selected randomly. No argument defaults to 1. The argument * will return all. So basically @array.pick(*) is a shuffle.

my @brackets = <[ ]> xx 3;
my $generated = @brackets.pick(*).join;

So we now have a string containing the opening and closing brackets randomly ordered. You can pass this string to the check_balance subroutine as input. Again, the development of this subroutine is covered in Part 1.

Lets see how we can receive command line arguments in a Perl 6 script. We will use this so that the user can specify how many times (n), each bracket should be generated.

Perl 6 has a special MAIN subroutine which will be called first in a script. The arguments to this MAIN subroutine are the arguments supplied at the command line. Neat!

sub MAIN(Int $n)
{
    say $n;
}

The above code says that this script will accept exactly one command line argument which should be an integer.

Lets run this script without any arguments.

$ ./cmd.p6
Usage:
 ./cmd.p6 <n>

You see, we get an error message.

Now we need non-negative integers. Each argument passed to the MAIN subroutine can be restricted using a where block.

sub MAIN(Int $n where { $n >= 0 })
{
    if $n == 0 {
        say '(empty) OK';
        exit;
    }

    # generate the brackets
    my @brackets = <[ ]> xx $n;
    my $generated = @brackets.pick(*).join;

    say $generated;
    say check_balance($generated) ?? 'OK' !! 'NOT OK';
}

Excellent! Less work for the programmer. Perl 6 supports some really cool subroutine signatures which I hope to cover in future posts.

Note the conditional operator which now consists of ?? and !!.

In future parts, I will cover how we can receive user input and finally how we can create and use a Perl 6 module.

Have fun!

Solving the Balanced Brackets task using Perl 6 – Part 1

I’ve been trying to learn Perl 6 for the past few months. I’ve done it all. i.e. the usual stuff. Download Rakudo, install it, read the Perl 6 book. I did learn some stuff but I got no satisfaction! There is absolutely no substitute for hands on work. Get your hands dirty.

Rosetta Code is a great website where all kinds of programming tasks are solved using various languages. Its a great tool to learn new languages or improve your skills in your current language of choice. So I decided to pick up a task from this website. The task I first picked is the Balanced Brackets task.

Nope. Don’t even think about it. Look at the task definition on the website, copy it, paste it somewhere, and close that browser tab. You are not going to scroll down on that tab and look at the solutions. Here is the task definition.

Task definition

  • Generate a string with N opening brackets (“[”) and N closing brackets (“]”), in some arbitrary order.
  • Determine whether the generated string is balanced; that is, whether it consists entirely of pairs of opening/closing brackets (in that order), none of which mis-nest.

Alright, lets approach this problem using TDD (test driven development). We will first create a series of tests all of which fail, and then gradually write the code so that all the tests pass.

In Perl 6, you can use the Test module. Its quite similar to the Perl 5 module. The only test we will be using is ok.

So here is how we write testing related code in Perl 6.

use Test;

ok (check_balance('[]') == True);
ok (check_balance('][') == False);
ok (check_balance('[[]]') == True);
ok (check_balance('][[]') == False);
ok (check_balance(']][[') == False);
ok (check_balance('[][]') == True);
ok (check_balance('[]][') == False);
ok (check_balance('[[[]]]') == True);
ok (check_balance('[][[[[]][]][]][]') == True);
ok (check_balance('[[]][][][[]][]') == True);
ok (check_balance('[[[][]][[]]]][[]') == False);

If you’re familiar with Perl 5 this should be easy enough to understand. We are checking the result of the check_balance subroutine (which we will write shortly). Now Perl 6 supports types. Strictly speaking, Perl 6 supports gradual typing. So it supports dynamic typing as well as static typing. The check_balance subroutine returns a value of type Bool which can have only two values – True or False. Note that True and False are not strings. The digit zero will evaluate to Bool::False but is of type Int.

Now lets write the basic stub of our check_balance subroutine.

sub check_balance(Str $b) returns Bool {
    return False;
}

Perl 6 supports subroutine signatures. In this case we define the subroutine as accepting a single parameter of type Str (string) and returns a value of type Bool. Inside this subroutine, $b is the supplied argument. By default, the arguments are passed by copy.

Now lets get to the meat of this task. I must confess it took me several tries to get the logic correct, so I won’t bore you with the details. But as you develop your subroutine you will see the benefits of writing the tests first.

We need a way to keep track of how many brackets have been opened (the character [), and make sure that each opened bracket has been closed (the character ]). If at any moment we see that the number of closed brackets are more than the number of opened ones, we can be sure that the balance is off. At the same time we can’t do this the other way round, as we can start off with any number of opening brackets and then close them.

if $c eq '[' {
    $num_opens++;
}

if $c eq ']' {
    $num_opens--;
    if $num_opens < 0 {
        return False;
    }
}

Here $c is each character in the string $b. So in effect, we need to apply the above code to each character of $b. Time for a loop! Lets approach this the easiest way. First, we need the number of characters in $b. That’s possible using $b.chars. So yes, in Perl 6 everything is an object and you can call methods on an object and you use the dot operator to do so. In Perl 6 the C-style for keyword is now loop.

loop (my $i = 0; $i < $b.chars - 1; $i++) {

    my $c = $b.substr($i, 1);

    if $c eq '[' {
        $num_opens++;
    }

    if $c eq ']' {
        $num_opens--;
        if $num_opens < 0 {
            return False;
        }
    }
}

From the above code snippet we can see that -

  • No parentheses required for the if conditional
  • You can call methods on an object using the dot operator
  • The C-style for keyword is called loop
  • String comparison operator is eq

At the end of this loop, we need to again check if the balance is correct. So $num_opens needs to be zero.

Here’s the complete subroutine.

sub check_balance(Str $b) returns Bool {

    my $num_opens = 0;

    loop (my $i = 0; $i < $b.chars - 1; $i++) {

        my $c = $b.substr($i, 1);

        if $c eq '[' {
            $num_opens++;
        }

        if $c eq ']' {
            $num_opens--;
            if $num_opens < 0 {
                return False;
            }
        }
    }

    return $num_opens == 0;
}

Now include this subroutine in your test script and all your tests should pass.

Lets dig deeper into Perl 6. After all, There’s more than one way to do it!

Calling $b.substr each time is a waste. Lets get all the characters of $b in an array and loop over that array.

sub check_balance(Str $b) returns Bool {

    my $num_opens = 0;
    my @chars = $b.split('');

    for (0 .. @chars.elems - 1) -> $idx {

        my $c = @chars[$idx];

        if $c eq '[' {
            $num_opens++;
        }

        if $c eq ']' {
            $num_opens--;
            if $num_opens < 0 {
                return False;
            }
        }
    }

    return $num_opens == 0;
}

What have we learned ?

  • Calling the split method on a string returns an array of characters
  • We replace the loop with a for, and iterate over the elements of the array @chars
  • @chars.elems return the size of @chars – an array
  • The use of the .. sequence operator (as in Perl 5)
  • We explicitly use the $idx variable as the topic variable instead of the default $_ inside the for loop
  • The sigil for accessing individual array elements is now the same as the sigil of the array, and is not the $ (as was in Perl 5). Similarly you would access a hash value using, for example, %colors{‘red’}, and not $colors{‘red’}

The .. sequence operator supports exclusivity. So a caret (^) on a side does not include the last (or first) number. The for loop can thus be written as

for (0 ..^ @chars.elems) -> $idx {
    ...
}

Perl 6 has the comb method for strings which will iterate over the characters of a string. Lets look at the entire for loop.

for $b.comb -> $c {

    if $c eq '[' {
        $num_opens++;
    }

    if $c eq ']' {
        $num_opens--;
        if $num_opens < 0 {
            return False;
        }
    }
}

Again note -

  • The for loop does not require parentheses

You can check out all the code on Github. In the coming posts we will see how to generate the input bracket randomly, how to accept user input and finally how to create a Perl 6 module.

Have fun!

 

Creating and using a Module in Perl 6

Perl 6 provides an easy way to chunk all related code together in a module. You can browse the code on Github.

Lets keep things simple. We will create a module which contains all math related code. Let write a simple sum subroutine which sums up the elements of an array.

module MyMath;

sub sum(@input) is export returns Int {
    return [+] @input;
}

The module keyword specifies the name of your module; in this example it is MyMath. We then define a sum subroutine which takes an array as its only argument and returns an Integer.

Yes. Perl 6 supports subroutine signatures.

We then use the + infix operator in prefix form to add up the elements of @input. So,

my $sum = [+] @input;

is the same as

my $sum = 0;
for (@input) {
    $sum += $_;
}

Now using this module is very simple.

use MyMath;

my @array = 4, 5, 7, 89, 12, 42;
say "Sum of @array.join(', ') is {sum(@array)}";

Since we added the is export trait to the sum subroutine it is already imported into the current namespace.

If you’re new to Perl 6 -

  • You don’t need parentheses to create an array/list.
  • You can call methods on an array
  • Code inside curly braces is interpolated

 

This blog now hosted on Amazon EC2

 

Yesterday I moved a server from Rackspace cloud to Amazon EC2. I must say setting up the Amazon EC2 instance was a bit frustrating as this was my first time and there are way too many options in the EC2 management console!

The advantage is now that this server is setup I can create an AMI (Amazon Machine Image) and then easily and very quickly create new instances. No need to install Apache, MySQL, Perl modules, etc.