
Planet Perl Six is an aggregator of select Perl 6 related blogs. The list of contributors changes periodically.
Planet Perl Six provides its aggregated feeds in Atom, RSS 2.0 and RSS 1.0, and its blogroll in FOAF and OPML
Today I've had some fairly good progress with Hitomi, the XML templater. Using the draft grammar moritz++ helped me build, I created a class that takes an XML document and translates it to a stream of events. This makes about half of the tests that I ported from Genshi last time pass; the other half of that test file concern tag soup input — I think I'll punt that one for now, and go for the lower hanging fruit: the classes Template and MarkupTemplate. With those, it should be possible to actually, you know, do some templating.
I'm getting more and more familiar with the original Python code, and starting to have some significant respect for the Genshi code base. It's simply a very well-thought-out piece of software. I can see why people like it. The project doesn't seem terribly active, unfortunately, so sometimes questions from me and others go unanswered on the #python-genshi IRC channel.
Is Hitomi a good name? jnthn++ pointed out today that it sounded very similar to "hit on me", and I find myself constantly writing either "Hitmo" or "Himoti". Then again, I kinda like that it means (or so I've read) "doubly beautiful", and I don't have a better suggestion at the moment.
Another thing that has been going on in the past week is that viklund++ said, almost in passing, that it'd be nice to have an XPath engine for Match objects. I thought it was a great idea, and incubated the project "Grampa" (short for "grammar paths") on github. I've since made some good progress on it, and it's already slightly useful. Not to mention that I've learned a few new things about XPath and EBNF that I didn't know before. pmichaud++ helped me with some questions on the latter.
How does that tie into Web.pm? Well, it turns out that at least two of the subprojects of Web.pm would benefit from XPath searches: Hitomi, and Happle (our Hpricot clone). This suggests that Grampa should really be a Match front-end to an XPath query back-end, so that the back-end can then be reused in other projects. I've been implementing Grampa with this in mind.
Finally, since it's nearing the end of my original part of the grant, I've taken a fresh look at doc/PLAN and refined it a little. No major course corrections were needed, which feels comforting. I'll probably write some more about the status of the subprojects in next week's blog post.
Another thing I plan to do in the coming week is start on my Web.pm talk for YAPC::EU. I thought I'd write the talk in Perl 6 Pod, and then do various conversions to end up with a PDF. Since most of the toolchain for doing that doesn't exist yet, I thought I'd better start now. 哈哈
I wish to thank The Perl Foundation for sponsoring the Web.pm effort.
Parrot releases are harder to count because of their prolific release cycle.
Brian Wisti, In Which Brian Whinges About The Perl 5 Release Schedule
This is a trivial nitpick (read the rest of the article! It's very good!), but Parrot releases are very, very easy to count. The same goes for Rakudo releases.
The other day someone asked what Parrot might look like in a hundred years. I laughed and thought, "What would its version number be?" Then I realized that I can predict its version number in 100 years. Parrot 101.6 will be out, with Parrot 101.7 on the way.
For all of the lofty talk about "stability" and "maturity" and "predictability" which results in Perl 5 not getting released, the fact that I can predict the release date and version number of a piece of software one hundred years in the future says something about the stability, maturity, predictability, and reliability of a very different kind of development process.
(Oh, and Alias -- I can crash several so-called stable releases of Perl 5 with a one-liner the same way you crashed Parrot in December 2008 with a short program. If you want to make the argument that the 30 stable monthly releases of Parrot in a row don't actually exist because they had bugs, the two so-called stable releases of Perl 5 from the same time period don't exist either. Ontological debates are easy to lose.)
The Perl 6 design team met by phone on 27 May 2009. Larry, Allison, Patrick, Jerry, and chromatic attended.
Larry:
time function to return a Rat use Allison:
Patrick:
root_new opcode in Parrotuse and import in RakudoJerry:
c:
Patrick:
Jerry:
Patrick:
Larry:
Patrick:
Larry:
(1, 2, 3) bound to an array...Patrick:
zip operator in slice context....zip($a,$b,$c) zip($a,$b,$c;$d) Larry:
Patrick:
Larry:
Patrick:
Larry:
Patrick:
Larry:
Patrick:
Larry:
Patrick:
Larry:
Patrick:
Larry:
Patrick:
zip($a, $b, $c) has three positional argumentszip($a, $b, $c; $d) has two, the first of which is itself a list/captureSubtitled "The Zen of not messing up your strings".
Handling non-ASCII strings in Perl 5 is a real pain, because there are no
real separate types for binary data and text strings. Mostly the operation
provides a context of either binary or string processing, but function like
length don't, so the answer is dependent on internal
representations about wich the programmer should never care.
In the Perl 6 language design we decided not to repeat that mistake. Since
Strings are objects like everything else, it's easy to invent new types. So in
essence we have two types relevant for our discussion, Str and
Buf.
A Str is notionally a sequence of characters, or a text
string. There's no character encoding attached to it, and while it is surely
stored in a specific encoding scheme internally, it's nothing that programmer
cares about.
A Str co-exists on two (at least) two levels, on codepoint and
grapheme level. A codepoint is everything that the Unicode consortium has
assigned a number and a name, like U+0065 LATIN SMALL LETTER E
or U+0300 COMBINING GRAVE ACCENT. A grapheme is either a
codepoint or a sequence of codepoints that are visually represented together,
for example the two codepoints mentioned before would be printed as a single
grapheme è.
The default level is grapheme, because that's closest to how humans usually
think of characters and text. Specific operations can override the default
abstraction level, or it can be adjusted by pragmas like use
codes;.
Of course you can also handle binary data in Perl 6. Such data is stored in
objects of type Buf. Notionally a Buf is a list of integers of a
fixed size. It has subtypes for common sizes buf8 is a sequence
of unsigned bytes, buf16 and buf32 store unsigned 16
and 23 bit integers.
When you communicate with anything outside of Perl 6, you'll need
Buf objects for that, because files and terminals only understand
byte streams, not character streams.
There are also a different kind of Bufs which enforce a
specific encoding, for example utf8 can only hold byte sequences
which can be interpreted as UTF-8. They are not strictly necessary, but
provide a nice, convenient interface for some operations.
Conversion between Str and Buf is called encoding, the other way round is
called decoding. For example "møøse" is a Str, and
"møøse".encode('Latin-1') returns a Buf, more specifically a
buf8.
On the other hand if you read some bytes from a socket and want to treat
the result as a text string, you decode it: my $str =
$buf.decode('UTF-16LE').
Mixing a Str and Buf that doesn't know about its own encoding in an operation like concatenation or comparison throws an exception, because those are the conditions where most Perl 5 programs mess up strings beyond all repair.
If you read the above, maybe you think that printing a Str to standard output is an error because the string doesn't know its encoding, so it can't represented as a byte stream. That's only half the truth; the output handle can also have knowledge about its own encoding.
When you open a file, you can either specify that it's opened as a binary
file, or you specify an encoding. In the former case reading from the handle
returns Bufs, in the latter Strs.
For the sake of convenience a pseudo encoding called Unicode
exists. (Yes, we know that Unicode defines a character repertoire, not a
character encoding). If there's a byte order mark (short BOM) at the start of
the stream, it is used to determine the encoding. If not, a very simple
autodetection is used: If the file is obviously UTF-16LE, UTF-16BE or UTF-32
(detectable by the position of the zero bytes when encoding ASCII characters)
then the detected encoding is used, otherwise as a fallback UTF-8 is
used. This autodetection scheme is the default.
We learned from the experience that cramming too many different semantics into a single data type is harmful. So now byte streams and text streams have different data types, and a clean interface for converting back and forth.
The specification is not set in stone so far, and no compiler implements the Buf type yet, but it is already planned for Rakudo.
Since this is an important topic to me I will continue to nag the implementors and language designers about it, and write tests to ensure a solid implementation.
It is probably not that interesting for most of the people but I have my excuses. What is more interesting - at least to me - is why others are involved.
After all there were already more than 40 people who made some contribution to Padre.
So I asked them to start writing down why are they involved. Some of them have already added themselves to the developers page and we started a separate page for translators though that one is new and has no been filled yet.
So why do I write Padre?
There is a short explanation on that page but let me bore you with a longer one here.
I have been teaching Perl 5 for almost 10 years now. Both beginner level and advanced courses. In the beginner courses the majority of the people use Windows with about 20-30 percent using Linux. Most of the Windows users use Notepad++ or a similar editor. Some of them can configure their editor to run the perl script right from the editor, others don't even know how to enable syntax highlighting for Perl 5. Some of the people on Windows don't know what the command line is but even those who know how to open the command prompt are either afraid of it or just dislike it.
Mind you these are not stupid people or anything like that. Some of them have many years of hardware design behind them. They are just used to some kind of IDEs.
Others might use Linux/Unix but many not by choice. In many cases the company they are working for gives them telnet access to an oldish Unix machine and tell them to code in Perl. They hardly know vi, they don't know how to configure syntax highlighting and they don't know how to install any other editor.
I have been using vim for many years and I can testify that it is a superb editor. Emacs is similary strong but I have not used it since university. The problem with both of them is that they are totally different from the editors most people are used to and their learning curve is long and steep. It takes several months or even years to become familiar with them. Most of the people don't want to invest that energy and I certainly don't have the time for that in a 4 days long Perl 5 course.
So I usually tell them to use whatever they are familiar with. I think I never had a student who picked Eclipse or Emacs. There were a few using vi/vim but most of the people used Notepad++ or a similar Windows based editor.
I don't think my students are too different from the average people learning and using Perl. Most of them will never write a full blown web application. Heck most of them won't have a need for object oriented coding as they write only 100-200 line long scripts in Perl.
They never get really familiar with Perl and they will always have to deal with strange code written by others. With all the other tasks they are required to do in their primary language or tool they will keep wondering what is $_ when they see it and will be surprised when they don't.
They will wonder what is the relationship between $_ and $_[0].
So my first objective was to provide a simple Notepad++ like editor with strong support for beginners or people with relatively little experience with Perl.
For example I'd like to make sure that Padre users will be able to highlight $_, press F1 and get an explanation. In case they highlight $_ from a $_[0] expression Padre should be clever enough to point this out and give an explanation on @_ and @_[0].
I knew it is a big task though I did not think it is soo big. In any case I knew I cannot handle this alone, especially as I am not such a good programmer. So from the very beginning I tried to make it interesting, accessible to experienced Perl 5 developers and in turn they made it fun and hackable.
Unfortunatelly most of the experienced Perl developers are also hard-core vim or emacs users and it is nearly impossible to move them away from their editor. Luckily there were a few who got interested by the idea of having a lot of control over their editor and that made the difference between a failing one man project to a project with a lot of potential.
Then at one point came the idea to integrate Parrot and Rakudo and try to provide a platform for Perl 6 development as well. With the awesome work of Ahmad M. Zawawi Padre has a lot to offer to anyone who wants to write Perl 6 code. With some more work we'll be able to integrate Parrot even better and then Padre will be able to handle any language running on top of Parrot.
While there are still lots of problems with Padre and installation can still be difficult it already more or less has the same power as Notepad++ on both Windows and Linux and probably on Mac too and it has some extra features that even vim people started to steal.
At the beginning of June the Vienna.pm organization generously committed to funding me for 1-day-per-week of Rakudo effort, but because of the Rakudo release, Parrot Virtual Machine Workshop, YAPC::NA, and a short vacation, today is the first day that I had available to really dedicate to the task. In fact, to catch things up a bit I plan to do another Rakudo day tomorrow or Thursday.
Here's what I accomplished for today's Vienna.pm-funded Rakudo day.
The biggest task I tackled for the Rakudo day was to be able to write operators in the setting (Perl 6) instead of PIR (RT #66826). In fact, I had actually done most of this last week during the YAPC::NA hackathon day, but interruptions then and a few annoying Parrot bugs kept me from marking the task as completely accomplished then. What this means is that we can now begin defining operators directly in Perl 6 code (perhaps with some inlined PIR), which moritz++ has already been exercising for infix:<...>, infix:<eqv>, and a few other operators. Over the next few weeks I expect we'll move even more operators out of PIR and into the setting.
The rest of today's Rakudo day was spent reviewing and cleaning up the RT queue; it had grown to over 400 tickets but by the end of the day Jonathan and I have shrunk it back down to 387. I think we collectively closed about 16 tickets today, and I responded with requests for clarification or updates on several more. Here are some of the highlights:
RT #66060 noted a problem that the .uc method would fail on some strings where .lc worked. I tracked this down to a Parrot issue in its handling of Unicode strings when ICU wasn't present, and refactored the code to be a bit more robust there.
RT #66640 noted that the minmax operator wasn't implemented, so after some discussion about what it should do I added it to the setting (using the operator features mentioned above).
In RT #66624, the exception message coming back from not finding a substring within a string was particularly misleading; I adjusted .substr to provide a more useful error message.
For RT #66928 .WHAT would not work on some subs like &infix:<+>; this was because some of the builtin operators are still using Parrot's MultiSub PMC instead of the Perl6MultiSub PMC, and those didn't have a mapping to the type object. Eventually all of the operators will become Perl6MultiSub; in the meantime I set Parrot MultiSub PMCs to map to the Multi() type objects in the same manner that other Parrot PMC classes are mapped to Perl 6 types.
RT #66818 noted a problem with unwanted flattening of %*VM in a for statement; this was because the contents of %*VM were incorrectly bound to the Hash directly instead of going through a non-flattening reference (Perl6Scalar). Eventually I expect %*VM to be initialized in the setting, though, which will provide a more robust and direct solution to this problem.
In RT #66840 it was discovered that precedence errors in the ternary operator would cause Rakudo to issue an error message and exit completely, instead of throwing a catchable exception. I tracked this down to PGE's OPTable handling of the ternary operator, it was actually using "exit" when the error occurred (probably because it came from before Parrot's exception model was firmly in place). This was changed to throw an exception instead; the actual exception message needs a bit of work but I expect that will come from the much larger PGE refactoring that will be done as part of the Hague grant.
Lastly, today I spent a good bit of time discussing Rakudo and Parrot build/install issues with Allison, and I think we have basic agreement on the changes we'll be making in order to get those working. Hopefully we can get all of that done in time for the July release.
So, that's my first Vienna.pm Rakudo day -- lots of little pestering bug fixes, and a key bit of infrastructure to fully enable writing the builtin operators in Perl 6. Later this week I plan to do a long-needed refactor of container handling in Rakudo, and maybe to get a more complete implementation of BEGIN blocks (which we massively cheat on at the moment).
Thanks again to Vienna.pm for sponsoring this work.
Pm
I'm back from a nice break in Italy and have been digging back in to Perl 6 stuff again. Today I've been doing a Vienna.pm-funded Rakudo day, and here's what I got up to.
First off, I went for a look through our RT queue. We now have over 400 tickets that are either new or open. While on the one hand that means we've a lot of work to do, it's also a sign that people, more and more, are playing with and exercising Rakudo. In just browsing through it, I found a bunch of things I could work on and hopefully resolve fairly easily during the day, and also another bunch of things that were already resolved. Just spotting the latter allowed me to mark 3 tickets resolved.
A couple of the things I worked on related to subtyping. Of note, the standard grammar accepted:
subset Foo of Int;
Without requiring a where clause. Rakudo now also accepts this, and our parsing is a little closer to STD.pm too (we parse traits on subtypes, but we don't do anything with them just yet). Next, I got Rakudo to support a neater syntax for declaring anonymous subtypes in signatures. If you just want to match a specific value, you can write the value in the signature, and that's it. For example, here is yet another way to do factorial (a recursive version).
multi factorial(0) { 1 }
multi factorial(Int $n) { $n * factorial($n - 1) }
say factorial(5); # 120
A signature :(0) is equivalent to :(Int $ where 0). This means that it will sort in the candidate list with Int. More generally, any literal value in where will get a nominal type based on the .WHAT of the value and have the value made into an anonymous subtype, so the signature :("tava") is just like :(Str $ where "tava"). I added some tests for all of this too.
Lyle++ had sent in a patch a while back for $*CWD and chdir. I took a look at these today. The $*CWD one looked pretty good, so I applied that with just a minor tweak. The chdir one needed some more attention and fixing up first, but I got that applied and extended the tests to better exercise it. Then I got both test files added to spectest.data. So now chdir and $*CWD are both functional. Here's some play with them in the REPL.
> my $fh = open("spectest.data", :r);
Unable to open filehandle from path 'spectest.data'
in Main (:1)
> say $*CWD;
C:\Consulting\parrot\trunk\languages\rakudo
> chdir "t";
> say $*CWD;
C:\Consulting\parrot\trunk\languages\rakudo\t
> my $fh = open("spectest.data", :r);
>
We had a couple of tickets relating to the interaction of //= and state variables. A little investigation, some discussion on #parrot and a fix later, I was able to unfudge tests and mark those resolved. A small inheritance bug was a similar story.
Finally, in preparation to improve type check failure error reporting and resolve at least one ticket in that area, I factored all type check error generation out to one routine, which we now call consistently. That means errors that previously missed out mentioning the expected and received types now do so, and the other issues I can fix - on some future Rakudo day - in one place, and everywhere that reports such errors will benefit.
In the course of the day, I also discovered a couple of other tickets that I had opened up to investigate at the start of the day were also already-fixed issues, so I made sure we had proper test coverage and got them closed up.
So, a pretty productive day. Thanks to Vienna.pm for funding!
Hello, don't mind me. I'm just going through a few MVC frameworks to see how they differ and how they're alike. I need the knowhow to create an MVC for Web.pm. Right now, my plan is to examine Rails, Catalyst, Django and Jifty. I'll write down my impressions of each of the in some kind of list, for future reference. Basically the only way you'd want to read this is if you want to laugh at how little I know about MVC frameworks.
Here's the list I got from watching this screencast:
Um. Well, in summary, that cool-aid sure seems to have an effect on me. I'll leave the comments open so that you people can tell me how Rails, despite all appearances, is really bad for your teeth and leaves skid marks on your puppy.
Next up: Catalyst.
This isn't a success story - it's only almost a success story.
On perlmonks.org we had a Golf challenge (ie writing code in as little characters as possible): write an implementation of the Euclidian algorithm in Perl 6.
I proposed a solution
which I liked very much, but which didn't work in Rakudo yet, because it
used the series operator infix:<...> (yes, three literal
dots) which isn't yet implemented in Rakudo. D'oh!.
I like Perl 6 discussions on Perlmonks, but every solution that shows a NYI-feature encourages the "Perl 6 is vapor-ware" thoughts and comments. So I decided to make it work, and decided to JFDI and implement the missing operator.
In general implementing a new operator in Rakudo is not much harder than implementing a function: all you have to do more is to add it to src/parser/grammar-oper.pg including precedence and associativity (both of which can be found in the spec.
For quite a while now built-in functions and methods can be written in Perl 6 now, so I also decided to write the new operator in Perl 6. Since lazy lists aren't implemented yet, I decided not to care about the lazy version, and did the eager version instead. This is what my code looked like:
multi sub infix:<...> (@lhs, Code $generator) { my $c = $generator.count; if $c > @lhs { fail 'the closure wants more parameters than given on the LHS'; } my @result = @lhs; my @r; # XXX work around http://rt.perl.org/rt3/Ticket/Display.html?id=66824 # this is a bit ugly.. since @a[1..1] returns a single item and not # an array, |@result[$one-item-range] throws the error # "argument doesn't array" while @r = $generator(|@(@result[*-$c..*-1])) { @result.push: @r; } return @result; }
This works... partly. It works only in the file it is defined in, not if it's defined in the setting library.
So to summarize: I have an implementation ready, but due to Rakudo bugs it can't go into mainstream Rakudo right now. JFDI, partly failed.
This is my first Perl 5 post ever. 哈哈
<masak> while I'm here, I'd like to talk about Modern Perl.
<masak> in y'all's opinion, what are the modules a Modern Perl 5 user should be aware of?
<masak> I'm thinking of things like Moose, List::Util, maybe Catalyst...
<claes> it all depends on what the task is
<lucs> masak: 5.10 in general maybe
<claes> using warnings, strict and perhaps indirect pragmas
<masak> I think things that we take for granted as good time-savers all qualify.
<masak> so maybe stuff like Getopt::Long too.
<claes> personaly I don't use Moose because I haven't had any use for it yet
<masak> for me as a Perl 6 user, it's not that difficult to see the use for Moose.
<masak> I saw a blog post recently that said that Moose even helped the blogger document things more succinctly.
<masak> that is, even when he wasn't using Moose, he was using habits gained from it to write better documentation.
<Hinrik> Perl::Critic, definitely
<claes> Devel::NYTProf
<Hinrik> some of the eventy things (AnyEvent, Coro, POE) too, if that's what your app requires
<Hinrik> and the various Test::* modules, of course
<masak> Hinrik: which ones, more exactly?
<Hinrik> Test::More usually works for me, along with some other specialized ones depending on the typo of app
<Hinrik> e.g. Test::Script to test if scripts compile
<Hinrik> masak: oh, and Devel::Cover is also quite helpful in determining test coverage
<cfedde> see also Modern::Perl
<cfedde> I think that the standard template will become 'use Modern::Perl; use Moose'
Feel the need to add something to the list? The comments are open.
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.
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);
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.
Last night I had one of those rapid prototyping sprints where everything goes just right. I wanted to scout the terrain for drawing a 3D Druid board using SVG.
The result is this. Yup, Perl 6 did that, with a little help from me.
It was very pleasing to see this image grow step by step. I literally started with a grey rectangle. Then I programmatically massaged the coordinates, adding projections, translations, scalings and rotations until I had what I wanted. Here's the code.
I still feel two things are missing.
Anyway, I've been wanting to do this for a long time, and I'm glad that when I finally sat down to do it, not only was the result quite satisfactory, but also the process of getting there. It's 2009, and I'm using Perl 6 to rapid-prototype 3D board games. Cool!
On behalf of the Rakudo development team, I'm pleased to announce the June 2009 development release of Rakudo Perl #18 "Pittsburgh". Rakudo is an implementation of Perl 6 on the Parrot Virtual Machine. The tarball for the June 2009 release is available from http://github.com/rakudo/rakudo/downloads .
Due to the continued rapid pace of Rakudo development and the frequent addition of new Perl 6 features and bugfixes, we continue to recommend that people wanting to use or work with Rakudo obtain the latest source directly from the main repository at github. More details are available at http://rakudo.org/how-to-get-rakudo .
Rakudo Perl follows a monthly release cycle, with each release code named after a Perl Mongers group. This release is named "Pittsburgh", which is the host for YAPC|10 (YAPC::NA 2009) and the Parrot Virtual Machine Workshop. Pittsburgh.pm has also sponsored hackathons for Rakudo Perl as part of the 2008 Pittsburgh Perl Workshop.
In this release of Rakudo Perl, we've focused our efforts on refactoring many of Rakudo's internals; these refactors improve performance, bring us closer to the Perl 6 specification, operate more cleanly with Parrot, and provide a stronger foundation for features to be implemented in the near future. Some of the specific major changes and improvements in this release include:
The development team thanks all of our contributors and sponsors for making Rakudo Perl possible. If you would like to contribute, see http://rakudo.org/how-to-help , ask on the perl6-compiler@perl.org mailing list, or ask on IRC #perl6 on freenode.
The next release of Rakudo (#19) is scheduled for July 23, 2009. A list of the other planned release dates and codenames for 2009 is available in the "docs/release_guide.pod" file. In general, Rakudo development releases are scheduled to occur two days after each Parrot monthly release. Parrot releases the third Tuesday of each month.
Have fun!
References:
[1] Parrot, http://parrot.org/
[2] YAPC|10 http://yapc10.org/yn2009/
[3] Parrot Virtual Machine Workshop, http://yapc10.org/yn2009/talk/2045
[4] Pittsburgh Perl Workshop, http://pghpw.org/ppw2008/
About a month ago we had a discussion about distributing Perl 6 modules, again. This time I also looked at cpan6.org and mailed Mark Overmeer about his progress and visions.
The discussion moved to the perl6-language mailing list, and I went to vacations. When I came back roughly three weeks later, there were nearly hundred messages on that subject in five different threads, and so far I didn't feel like reading it all. (Additionally my mail server went down during that time, so I didn't even have them in my mailbox).
So instead of discussing things, I started to do something: I added meta data files to my Perl 6 JSON parser and uploaded it to CPAN. I think that's the first Perl 6 module on CPAN, discounting some modules included in distributions like pugs and v6.pm.
Since the documentation is in Perl 6 Pod, search.cpan.org doesn't display it properly. So my next steps will be to find out whom I can prod to implement Perl 6 Pod rendering and indexing, or if I have to do that myself (and if yes, on which code base).
In parallel I'll try to get the proto hackers to install from tarballs, or write that myself too. In the end I'd want Perl 5 and Perl 6 modules to coexist on CPAN, presumably with the option to select packages implemented in either language for searching.
The Perl 6 design team met by phone on 20 May 2009. Larry, Allison, Patrick, Jerry, Nicholas, and chromatic attended.
Larry:
each to make it a conjectural junctionimport declarator implied by use but usable explicitlyimport with an inline module or role declaration, it'll perform the exporttrait_auxiliary and trait_verb, which fill the same syntactic category, we have trait_mod IS or TRAIT_IS or APPLY_IS, or some suchrw or readonly traits aren't types.&foo $.foo, call a code reference as if it were a method& is also a code reference; ought to be allowed there too.&!foo =end for your =begin, except in the case of =begin END infix:<< >> and then a signature>>( is now specifically not a hyperoperator within interpolation>>.( isPatrick:
c:
Patrick:
qx// quoting termAllison:
Nicholas:
c:
Nicholas:
Patrick:
Nicholas:
Jerry:
Patrick:
Jerry:
Patrick:
Jerry:
For the full article visit Perl 5 to Perl 6 - Arrays
I'm working mostly on Hitomi, a Perl 6 port of the Python templating engine Genshi. In the past week, I decided to dive into Genshi, looking at how data flows from the template to the finished result. I now have a pretty good understanding of this, so I thought I'd expand a bit on it here.
Genshi's fundamental data structure is called Stream, and it looks very much like a sequence of SAX events to me: open-tag, close-tag, text, processing-instruction, etc. Different transformations are then applied to a stream to yield the final result. A transformation could be something like "remove all <script> elements" or "shorten all posts that are longer than 400 characters". A stream modified in-place, but combine with a transformation to produce a new stream. The nice thing is that the actual templating is also expressed as a series of this kind of transformations. But the Genshi user can easily provide her own transformation on top of the standard ones.
I like this model very much. It feels extremely clean and extensible. I decided to port as much as I can to Hitomi. My short-term goal is to make things round-trip using the streams, and to that effect, I've ported a test file with 89 tests from Genshi to Perl 6.
It's still not totally clear to me how text is converted to a stream and then back. I can easily picture how a stream event knows how to serialize itself back into text, so the mystery on that side isn't very great; it's just that I haven't found the actual Python code for it yet. On the stream generation side, the data flow disappears into a Python-Expat library. Delegating XML parsing to a third party also seems like an exceedingly good idea to me.
Can we do the same thing — delegate to Expat, or some other suitable library — in Hitomi? I think so, and the Parrot documentation seems hopeful. I'd very much like to get that working. But in the short run, I'm pondering whether it might not be easier to make a small, throwaway XML parser out of the bits and pieces we developed as prototypes. I could make it a separate class and call it Impostor, to make sure we remember to remove it later.
Another issue I ran into is one of encoding. viklund++ has been doing heroic work in the past week making November handle UTF-8 correctly. The reason this is heroic is that Rakudo doesn't have a model for string encodings yet. The information has to be forced out of Rakudo against its will, and I've heard viklund mutter darkly about hacks and workarounds lately... It all culminated in a good discussion on #perl6 last night, and pmichaud++ promised to make a preliminary implementation of .encode (for Str) and .decode (for Buf), if we just sat down and wrote some tests to show what we expected these to do.
Looking forward a bit; I think there's a good chance we'll have something usable with Hitomi before my original grant period is over. After that, it might be a good idea to start looking at the port of Ruby's Hpricot (for manipulating and searching HTML documents), and to start digging into the MVC quagmire. I still expect to do some preliminary MVC investigations before that, though.
I wish to thank The Perl Foundation for sponsoring the Web.pm effort.
Just writing in to say that I'm too tired to blog today about the progress today, due to all the progress today.
Tomorrow I'll put together a summary of the last "week" of Web.pm. Who knows, I might even be coherent by then.
In the meantime, for those of you who bothered to read all three paragraphs of a post called "No update today", here's what I currently have as my desktop background. I just can't stop analyzing that picture, it's mesmerizing.
The Perl 6 design team met by phone on 13 May 2009. Larry, Allison, Patrick, Jerry, Will, Nicholas, and chromatic attended.
Larry:
is export augment slang, we have a way of embedding grammar modifications inline%*LANG now holds the whole language braid$*PARSER variable is just the MAIN element of that=for; now it doesPatrick:
Block c:
Patrick:
Allison:
Jerry:
Larry:
Patrick:
Will:
Patrick:
load_library problemNicholas:
$foo ~~ [ 1, 2, [ 3 .. 5 ] ] won't work eitherRange objects lazilyc:
Nicholas:
Patrick:
For the full article visit Perl 5 to Perl 6 - Scalars
The Perl 6 design team met by phone on 06 May 2009. Larry, Allison, Patrick, Nicholas, and chromatic attended.
Larry:
comb now defaults to matching single characterswords method now does what comb used to dopick List or a Capture which returns an Item Item pick is one of those functionshas has if you have multiple attributesq, it starts at the current q-ish language in your braidgimme5 try in parsinghides trait\c notation for characters allows any radix of integer inside the list\c, \o, and \x notations all parse consistently now:: in it, assumes you're referring to a subpackage of the current lexical scope$?foo) with a virtual function for lookupYOU_ARE_HERE stub used to define the effective insertion location of your code into a Setting Setting's context for use by other compilation units||s suppressed panic messages//)Patrick:
Array and List implementationList inherits from ResizablePMCArray Allison:
c:
Patrick:
leave semanticsAllison:
Patrick:
Allison:
Patrick:
ReturnContinuation c:
Patrick:
set_returns Allison:
Patrick:
Sub's current contextSub to register behavior to execute just before it exitsAllison:
LEAVE hooks in Perl 6?Patrick:
push_action opcodeAllison:
Patrick:
ONEXIT or LEAVE hooks on Subs in ParrotAllison:
Subs to have thatPatrick:
Allison:
NEXT and LAST etcPatrick:
LEAVE is that it's not exception-basedAllison:
SubsPatrick:
Nicholas:
Larry:
c:
Larry:
Nicholas:
Larry:
c:
Larry:
Patrick:
Larry:
Patrick:
Larry:
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.
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.
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.
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);
}
}
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)
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
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.
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.
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