Perl 6

Embedding Parrot in Perl 6

Posted by Daniel on June 20, 2009
Perl 6, Programming / No Comments

One of the interesting things about Rakudo is that you can embed Parrot assembly code (PIR to be exact) into Perl 6 code. With this you can optimize critical parts of the code and you can expose additional Parrot features to Perl 6. Let’s start with a hello-world example:

Q:PIR {
	say "Hello world"
};

Though it is not obvious right now, the stuff inside the Q:PIR { ... }; is parrot code.

Parameters

Of course, embedded Parrot code would be pretty useless if you couldn’t send parameters in and get results out. Here is a simple Parrot routine that takes two parameters, adds then and returns the result:

sub ($a,$a) = (3,4);
sub $result = Q:PIR {
	# Input.
	$P0 = find_lex '$a'
	$P1 = find_lex '$b'

	# Compute the sum.
	$I0 = $P0
	$I1 = $P1
	$I2 = $I0 + $I1

	# Return it.
	%r = box $I2
};
say $result;

Yes, that’s quite verbose. PIR is not much higher level than an assembly language. The $P0, $P1, … are Parrot registers. The $P* registers hold Parrot objects, and the $I* registers hold integers. A more interesting example would be a factorial function:

sub factorial(Int $n where {$n >= 0}) {
	return 1 if $n == 0;
	return Q:PIR {
		# Define variables.
		.local int ans, n

		# Input.
		$P0 = find_lex '$n'
		n = $P0

		# Compute the answer.
		ans = 1
		LOOP:
			ans *= n
			n -= 1
			if n > 1 goto LOOP

		# Return it.
		%r = box ans
	};
}
say "5! = " ~ factorial(5);

Exposing Parrot libraries to Perl

A specially neat feature of embedded Parrot is that you can expose Parrot libraries to Perl. For example, Parrot comes with support for the MD5 digest function, which itself comes from the OpenSSL library:

sub md5(Str $text) {
	my $binary = Q:PIR {
		.local string text
		.local pmc digest

		# Input.
		$P0 = find_lex '$text'
		text = $P0

		# Load digest library.
		$P1 = loadlib 'digest_group'
		digest = new 'MD5'

		# Calculate the digest.
		digest.'Init'()
		digest.'Update'(text)
		$S0 = digest.'Final'()

		%r = box $S0
	};
	# Convert to hex.
	return join '', map {sprintf '%02x', (ord $^a)}, $binary.comb;
}
say md5("The quick brown fox jumps over the lazy dog");

The resulting library is of course much simpler and runs much faster than anything we could code in pure Perl. And this will run wherever Rakudo is available, without the need for a separate compilation step.

Perl 6 and the Josephus problem

Posted by Daniel on June 12, 2009
Perl 6, Programming / 6 Comments

The Josephus problem in Perl 6, Python and Ruby

In today’s post, I would like to compare the OOP syntax of Perl 6, Python and Ruby. To this effect, I decided to show you an implementation of the Josephus problem in each language. Wikipedia describes the Josephus problem:

There are people standing in a circle waiting to be executed. After the first man is executed, certain number of people are skipped and one man is executed. Then again, people are skipped and a man is executed. The elimination proceeds around the circle (which is becoming smaller and smaller as the executed people are removed), until only the last man remains, who is given freedom. The task is to choose the place in the initial circle so that you survive (are the last one remaining).

The problem is named after Flavius Josephus, a Jewish historian living in the 1st century. As the legend goes, he and his 40 comrade soldiers were trapped in a cave, surrounded by Romans. They chose suicide over capture and decided that they would form a circle and start killing themselves using a step of three. As Josephus did not want to die, he was able to find the safe place, and stayed alive.

Acknowledgement

The idea to use the Josephus problem to compare these languages is not my own. The idea comes from danvk.org who used it to compare Perl 5, Python and Ruby. I have copied his Python and Ruby code and I added the Perl 6 code of my own.

A quick note

I have tried to normalize the code as much as possible, so that you can get a better impression of the OOP syntax in each language. I will not benchmark the code, and I will keep my commentary to a minimum. The idea is that you see the OOP syntax of each language, with minimum influence from me.

Writing the class

Perl 6 (tested with Rakudo)

class Person {
	# $. means "public", "is rw" means it is writable.
	has ($.position, $.succ is rw);
	has $.alive is rw = True;

	# Stringify
	method Str() {
		"Person $.position, " ~ ($.alive ?? "alive" !! "dead")
	}
	# Create a linked chain of people.
	method createChain($n) {
		return self unless $n > 0;
		$.succ = Person.new(position => $.position + 1);
		$.succ.createChain($n-1);
	}
	# Kill every nth person. Stop killing if I'm the last one.
	method kill($pos is rw, $n, $remaining is rw) {
		return $.succ.kill($pos, $n, $remaining) if !$.alive;
		return self if $remaining == 1;

		if $pos == $n {
			$.alive = False;
			$pos = 0;
			$remaining -= 1;
		}
		$.succ.kill($pos+1,$n, $remaining);
	}
}

Python (tested with 2.5.2)

class Person:
	# Initialize
	def __init__(self,pos):
		self.position = pos
		self.alive = True

	# Stringify
	def __str__(self):
		status = "alive" if self.alive else "dead"
		return "Person #%d, %s" % (self.position, status)

	# Create a linked chain of people.
	def createChain(self,n):
		if n > 0:
			self.succ = Person(self.position+1)
			return self.succ.createChain(n-1)
		else:
			return self

	# Kill every nth person. Stop killing if I'm the last one.
	def kill(self,pos,n,remaining):
		if not self.alive:
			return self.succ.kill(pos,n,remaining)
		if remaining == 1:
			return self
		if pos == n:
			self.alive = False
			pos = 0
			remaining -= 1
		return self.succ.kill(pos+1,n,remaining)

Ruby (tested with 1.8.7)

class Person
	# Accessor and mutator methods
	attr_reader :position, :succ, :alive
	attr_writer :position, :succ, :alive

	# Initialize
	def initialize(pos)
		@position = pos
		@alive = true
	end
	# Stringify
	def to_s
		"Person \##@position, #{@alive ? 'alive' : 'dead'}"
	end
	# Create a linked chain of people.
	def createChain(n)
		return self unless n > 0
		@succ = Person.new(@position + 1)
		@succ.createChain(n-1)
	end
	# Kill every nth person. Stop killing if I'm the last one.
	def kill(pos,n,remaining)
		return @succ.kill(pos,n,remaining) if !@alive
		return self if (remaining == 1)

		if pos == n
			@alive = false
			pos = 0
			remaining -= 1
		end
		@succ.kill(pos+1,n,remaining)
	end
end

Comments

All three classes are straight forward, and almost exactly the same size. Perl 6 is a bit shorter, but the differences are insignificant:

Perl 6 Python Ruby
Lines of code* 23 25 27
Characters* 546 578 549

* Not including comments.

Note: A reader mentioned that a better way to do Ruby is to replace “attr_reader” and “attr_writer” by a single “attr_accessor”. With this change, Ruby is the shortest by character count.

There are things I could have done to make each language shorter, but my goal was to make each code sample clear and legible. Besides, you shouldn’t pick a language because you can save 3 lines of code. It makes more sense to see if you like the syntax and the over-all “feel” of the language, and that is a much more personal decision.

On a personal note, I don’t like the Python syntax as much… passing “self” explicitly, double underscores… it feels a bit hackish, but that’s just me. In turn, I like the Ruby and Perl 6 syntax. I can’t decide which I like better. Both look very clean and very clear.

Using the classes

Finally, this is how you would use these classes:

Perl 6

my $orig = 40;
my $nth = 3;

my $first = Person.new(position => 1);
my $last = $first.createChain($orig-1);
$last.succ = $first;

my $winner = $first.kill(1,$nth,$orig);
say "Winner: ", $winner;

Python

orig = 40
nth = 3

first = Person(1)
last = first.createChain(orig-1)
last.succ = first

winner = first.kill(1,nth,orig)
print "Winner: ", winner

Ruby

orig = 40
nth = 3

first = Person.new(1)
last  = first.createChain(orig-1)
last.succ = first

winner = first.kill(1,nth,orig)
puts "Winner: " + winner.to_s

RPN calculator in Perl 6

Posted by Daniel on June 06, 2009
Perl 6, Programming / 5 Comments

Here is something fun. Let’s make a full RPN calculator in Perl 6. In the process we’ll learn a lot about Perl 6’s cool grammar features.

Regexes on steroids

Perl 6 extends Perl 5’s regular expressions to make a full grammar language. Btw, we no longer say “regular expression”, we just say “regex”. The first feature I’ll introduce is the token. A token is basically a regex with a name so you can refer to it later. For example:

token Op {'/' || '*' || '+' || '-'};
token Value { \d+[\.\d+]? };

The first token matches the arithmetic operators + – * /. The second token matches numeric values. You can use these tokens inside a regex. For example, the following matches one or more Ops:

$str ~~ / <Op> + /

Changes compared to Perl 5:

  • Space is not significant in a P6 regex. You can space things out to make the regex more readable.
  • If you put single quotes around any text, the regex matches that text literally. So instead of writing \* you can write ‘*’
  • Now we use ~~ instead of =~

An RPN grammar

We can write tokens that refer to other tokens in order to build more complex grammars. A RPN calculator is basically a list of values and operators. Thus, we can complete the RPN grammar with:

# An "item" is either a value or an operator.
token Item { <Value> || <Op> };

# An "expression" is one or more items separated by white space.
token Expr { [<ws> <Item> <ws>]+ };

The <ws> token is provided by Perl 6. It is similar to \s* but it does not match the inside of a word. For example, the string “hello” does not match <ws> but the string “2+2″ does. Using tokens that refer to other tokens (including recursive definitions) you can build very complex grammars with Perl 6. In fact, the reference grammar of Perl 6 itself is written in Perl 6.

Procedures and control flow

At some point we’ll need a function to compute the result of two values and an operator. In Perl 6 you write procedure parameters explicitly, as you do in other languages:

sub do_op($lhs, $rhs, $op) {
	given $op {
		when '*' { $lhs * $rhs }
		when '+' { $lhs + $rhs }
		when '-' { $lhs - $rhs }
		when '/' { $lhs / $rhs }
	}
}

And here you can see Perl 6’s brand new switch statement. The keywords given and when may be less familiar than switch and case, but they are more natural and read better.

This would be a good time to see the new syntax for for loops:

for @array -> $elem {
	say $elem;
}

Here you can also see the say keyword which is very much like print except that it automatically adds the \n character at the end of the string.

Main program

Now we are ready for the main program logic. Start with an skeleton:

# Read from the command line.
my $str = @*ARGS[0];

if $str ~~ /^ <Expr> $/ {
	# Do something.
} else {
	say "This is not an RPN expression.";
}

A few things merit mention:

  • The array @*ARGS contains the command arguments.
  • In Perl 6, when you get a value of an array, you keep the @ symbol. So the first command argument is @*ARGS[0].
  • The round brackets in an if-statement are now optional.

After a successful match, the match result is put in the $/ variable. This variable is similar to Perl 5’s $1, $2, … but more powerful. In particular, you can refer to token matches by name:

if $str ~~ /^ <Expr> $/ {
	$/<Expr>;            # <-- The Expr matched.
	$/<Expr><Item>;      # <-- A list of Item tokens.
	$/<Expr><Item>[0];   # <-- The first Item token.
}

We saw earlier how to step through an array using a for loop. We can use $/<Expr><Item> the same way:

if $str ~~ /^ <Expr> $/ {
	for $/<Expr><Item> -> $item {
		# Do something with $item.
	}
}

Now we know enough Perl 6 syntax to finish the program:

if $str ~~ /^ <Expr> $/ {
	my @stack;
	for $/<Expr><Item> -> $item {
		if $item<Value> {
			@stack.push($item<Value>);
		} else {
			my $v1 = @stack.pop;
			my $v0 = @stack.pop;
			@stack.push(do_op($v0,$v1,$item<Op>));
		}
	}
	say @stack[0];
}

I trust that you can follow the algorithm. If not, see the Wikipedia page on RPN.

The full program

Now we are ready to see the entire program together.

token Op {'/' || '*' || '+' || '-'};
token Value { \d+[\.\d+]? };
token Item { <Value> || <Op> };
token Expr { [<ws> <Item> <ws>]+ };

# Read from the command line.
my $str = @*ARGS[0];

if $str ~~ /^ <Expr> $/ {
	my @stack;
	for $/<Expr><Item> -> $item {
		if $item<Value> {
			@stack.push($item<Value>);
		} else {
			my $v1 = @stack.pop;
			my $v0 = @stack.pop;
			@stack.push(do_op($v0,$v1,$item<Op>));
		}
	}
	say @stack[0];
} else {
	say "This is not an RPN expression.";
}

sub do_op($lhs, $rhs, $op) {
	given $op {
		when '*' { $lhs * $rhs }
		when '+' { $lhs + $rhs }
		when '-' { $lhs - $rhs }
		when '/' { $lhs / $rhs }
	}
}

Now you can save this to a file (RPN.pl) and run it with:

perl6 RPN.pl  "5 4 + 3 / 5 3 - *"

Exercise

Modify the program to add error checking: Check that @stack has size at least 2 before running an operator and that it has size 1 before returning a result. Use +@array to get the size of an array.

Perl 6 First Steps

Posted by Daniel on June 05, 2009
Perl 6, Programming / No Comments

I have been working more with Perl 6 / Rakudo. I have contributed a few bug reports, and I have now ported six of the Debian shootout benchmarks to Perl 6. I’m adding all the benchmarks to the perl6-examples git repository:

git clone git://github.com/perl6/perl6-examples.git

The benchmarks are located in the ’shootout’ directory. The benchmarks implemented include Fasta, Regex-DNA, K-Nucleotide, N-Body and Reverse-Complement.

Performance

Since I mentioned benchmarks, I guess I have to mention performance…

As you might expect for a project at this stage, Rakudo is very slow. Most benchmarks run about 500 times slower than Perl 5. But that’s normal. There has been no optimization work on Rakudo, since the focus is to get the functionality done (and premature optimization is the root of all evil). In the long term, there is no reason why Perl 6 couldn’t be faster than Perl 5, thanks to its simpler grammar and its type system.

Personally I wouldn’t worry about the performance of Rakudo at this point. Besides, Rakudo is more than fast enough for a lot of simple tasks like admin scripts. I plan to rewrite my backup script in Perl 6 and run it on Rakudo.

The Perl 6 experience

So far, the experience of writing Perl 6 code has been quite pleasant. I really like the Perl 6 syntax. When I convert Perl 5 code to Perl 6 I find that the result is always clearer, always easier to read, usually shorter, never longer. The syntax is more regular (a traditional problem with Perl) and yet it is more succinct and flexible (Perl’s traditional strengths). I feel that with Perl 6 it is easier to just say what I mean. I’m impressed.

Brainfuck interpreter in Perl 6

Posted by Daniel on May 30, 2009
Perl 6, Programming / No Comments

I wrote a Brainfuck interpreter in Perl 6 (largely inspired by Acme::Brainfuck). Here it is in its entirety:

# Read the program.
my $program = $*IN.slurp;

# Compile to Perl 6.
$program .= subst(/\$/, 'P; };', :g);
$program .= subst(/(\++)/, { 'P += ' ~ $0.chars ~ ';' }, :g);
$program .= subst(/(\-+)/, { 'P -= ' ~ $0.chars ~ ';' }, :g);
$program .= subst(/(\>+)/, { '$ptr += ' ~ $0.chars ~ ';' }, :g);
$program .= subst(/(\<+)/, { '$ptr -= ' ~ $0.chars ~ ';' }, :g);
$program .= subst(/\./, 'print chr P;', :g);
$program .= subst(/\,/, 'P = ord getc;', :g);
$program .= subst(/\[/, 'while (P) {', :g);
$program .= subst(/\]/, '};', :g);
$program .= subst(/P/, '@P[$ptr]', :g);
$program  = 'my @P = (); my $ptr = 0;' ~ $program;

# Run
eval $program;

Here is “Hello world” in Brainfuck (taken from Wikipedia):

++++++++++    initializes cell zero to 10
[
   >+++++++>++++++++++>+++>+<<<<-
]             loop sets the next four cells to 70/100/30/10
>++.          print   'H'
>+.           print   'e'
+++++++.              'l'
.                     'l'
+++.                  'o'
>++.                  space
<<+++++++++++++++.    'W'
>.                    'o'
+++.                  'r'
------.               'l'
--------.             'd'
>+.                   '!'
>.                    newline

To run the program, just do: perl6 brainfuck.pl < hello.bf

Perl 6

Posted by Daniel on May 27, 2009
Perl 6, Programming / No Comments

This week I’ve been experimenting a little with Perl 6. It began as a quick question on IRC and somehow I ended up writing sample scripts in Perl 6. This week I ported the regex-dna benchmark to Perl 6, and I intend to port a few others. You can download it here.

One thing that’s new about Perl 6 is that it is a specification, similar to C, C++ and Java. Any product that meets the spec and passes the test suite can be called Perl 6 (there are many C compilers, and none of them is “the official C compiler”).

The implementation I have been experimenting with is Rakudo (compiler written in Perl 6 and Parrot assembly language) which seems to be the most active and the most complete. You can already write some Perl 6 programs with the Rakudo compiler. There is a wiki called November, a board game called druid, and a few others. Other notable implementations include Pugs (interpreter written in Haskell) and SMOP (interpreter written in C).

Buy cheap softwarebuy adobe softwaredownload software software sales oem software