January 2016 Archives

Perl 6 .rotor: The King of List Manipulation

Rotor. The word makes a mechanic think about brakes, an electrical engineer about motors, and a fan of Red Letter Media YouTube channel about poorly executed films. But to a Perl 6 programmer, .rotor is a powerful tool for list operations.

Break up into chunks

At its simplest, .rotor takes an integer and breaks up a list into sublists with that many elements:

say <a b c  d e f  g h>.rotor: 3
>>>OUTPUT: ((a b c) (d e f))

We have a list of 8 elements, we called .rotor on it with argument 3 and we received two Lists, with 3 elements each. The last two elements of the original list we not included, because they don't make up a complete, 3-element list. That can be rectified, however, using the :partial named argument set to True:

say <a b c  d e f  g h>.rotor: 3, :partial
>>>OUTPUT: ((a b c) (d e f) (g h))
say <a b c  d e f  g h>.rotor: 3, :partial(True)
>>>OUTPUT: ((a b c) (d e f) (g h))
say <a b c  d e f  g h>.rotor: 3, :partial(False)
>>>OUTPUT: ((a b c) (d e f))

Here's what we've learned so far, used as a crude means to fit a chunk of text into 10-column width:

"foobarberboorboozebazmeow".comb.rotor(10, :partial)».join».say
>>>OUTPUT:
    foobarberb
    oorboozeba
    zmeow

We broke up the string into individual letters with .comb method, then we .rotor them into 10-element lists, specifying that :partial lists are fine too, and lastly we use a pair of hyper method calls to .join and .say each of those sublists.

Mind The Gap

Say, you're receiving input: you get a word, its French translation, and its Spanish translation, and so on for a whole bunch of words. You want to output only a particular language, so we need to somehow skip over some items in our list. .rotor to the rescue!

Specifying a Pair of integers as the argument makes .rotor break up the list into $key elements, with $value gap in between. Easier to see in the example:

say ^10 .rotor: 3 => 1, :partial
>>>OUTPUT: ((0 1 2) (4 5 6) (8 9))
say ^10 .rotor: 2 => 2, :partial
>>>OUTPUT: ((0 1) (4 5) (8 9))

On the first line, we have a range of integers from 0 to 9, we're asking .rotor to break that up into lists of 3 elements (including partial lists) and use a gap of 1. And indeed, you can see the output is missing number 3 as well as 7. Those are the gaps we skipped. In the second example, we've increased the gap to 2, and broke up the list into 2-element sublists: the 2, 3, 6, and 7 are the numbers that fell into gaps and were not included. Back to our exquisitely convoluted translations program:

enum <English French Spanish>;
say join " ", <Good Bon Buenos morning matin días>[French..*].rotor: 1 => 2;
>>>OUTPUT: Bon matin

We cheatsy-doodle with an enum and then use the [LANG..*] to toss the head of the list. The French in our example is enumerated into integer 1, which means [1..*] gets rid of the first element. Then, we use .rotor to make 1-element lists with a 2-element gap. This makes it skip over the words for languages we're not interested in.

Now, I'm sure some in the audence are currently throwing tomatoes at me and saying I'm going mental with my examples here... Let's look at something more real-worldly.

Overlaps

You have a list and you want to Do Things™ based on whether the next item is the same as the current one. Typically, this would involve a loop and a variable holding the index. You check the index+1, while also checking you've not reached the upper boundary of the list. Sounds tedious. Let's use .rotor instead!

We've already learned above that using a Pair we can introduce gaps, but what if we make the gap negative? It actually works!

say <a a b c c c d>.rotor: 2 => -1
>>>OUTPUT: ((a a) (a b) (b c) (c c) (c c) (c d))
say <a a b c c c d>.rotor(2 => -1).map: {$_[0] eq $_[1] ?? "same" !! "different"}
>>>OUTPUT: (same different different same same different)

On the first line, we're just printing the results from .rotor to see what they look like and on the second line, we're performing the actual comparison and acting accordingly. Looking at the first result: we get 2-element lists, where the first element is the element from the original list and the second element is the one that follows it. That is, were we to print just the first elements of our sublists, we'd receive our original list back, minus the last element. The second elements are all just a bonus!

All Out

A single Int or a Pair are not the only thing .rotor can accept. You can specify additional positional parameters that are Ints or Pairs to break up lists into sublists of different sizes, with different gaps between them.

Say, I have a custom daemon that creates logs about users that access it. The log is in plain text, each record follows the other. Records are multi-line and always look something like this (two records + separator shown):

IP: 198.0.1.22
Login: suser
Time: 1454017107
Resource: /report/accounting/x23gs
Input: x=42,y=32
Output: success
===================================================
IP: 198.0.1.23
Login: nanom
Time: 1454027106
Resource: /report/systems/boot
Input: mode=standard
Output: success

Each item contains a "header" with user information and resource they tried to access, as well as the "operation" they wanted to execute. In addition, each item is separated by a double-line. I would like to print the header and the executed operation, and I want Resource: to be present in both.

To parse this, we could use Grammars, but .rotor can do the trick too:

for 'report.txt'.IO.lines».indent(4).rotor( 4 => -1, 3 => 1 ) -> $head, $op {
    .say for "Header:",    |$head,
             "Operation:", |$op, '';
}

>>>OUTPUT:
    Header:
        IP: 198.0.1.22
        Login: suser
        Time: 1454017107
        Resource: /report/accounting/x23gs
    Operation:
        Resource: /report/accounting/x23gs
        Input: x=42,y=32
        Output: success

    Header:
        IP: 198.0.1.23
        Login: nanom
        Time: 1454027106
        Resource: /report/systems/boot
    Operation:
        Resource: /report/systems/boot
        Input: mode=standard
        Output: success

We fetch lines from file report.txt with 'report.txt'.IO.lines. To make output prettier, we indent each line with 4 spaces by calling .indent(4) on each item using the hyper operator (»). Now comes .rotor! We use it to break up lines into repeating chunks of 4 and 3 items: that's items for our header and our operation. After grabbing the 4-element chunk, we use a negative gap to backtrack and include Resource: line in our operation chunk as well. In the 3-element chunk, we use a positive gap, to skip over the separator line.

Afterwards, we use a for loop and give it two variables with -> $head, $op, so it loops over two items at a time. Inside the loop, we merely print each log item onto the screen. Since $head and $op are Lists, we use the pipe (|) character to slip them in.

Keep in mind, the pattern you supply to .rotor can be dynamically generated! Here we use a sine to generate it:

say ^92 .rotor(
    (0.2, 0.4 ... 3).map: (10 * *.sin).Int # pattern we supply to .rotor
).join: "\n"'
>>>OUTPUT:
    0
    1 2 3
    4 5 6 7 8
    9 10 11 12 13 14 15
    16 17 18 19 20 21 22 23
    24 25 26 27 28 29 30 31 32
    33 34 35 36 37 38 39 40 41
    42 43 44 45 46 47 48 49 50
    51 52 53 54 55 56 57 58 59
    60 61 62 63 64 65 66 67 68
    69 70 71 72 73 74 75 76
    77 78 79 80 81 82
    83 84 85 86 87
    88 89 90
    91

So whether you're an electrician, mechanic, or anyone else, I hope you'll find .rotor a useful multipurpose tool.

Update 1:

It's been pointed out to me that

"foobarberboorboozebazmeow".comb.rotor(10, :partial)».join».say

Is better written as

"foobarberboorboozebazmeow".comb(10)».say

100+ Modules for Adoption! (Bit Rot Thursday)


EDIT: Just a note for PAUSE admins, as some emailed me, any module listed on this post can be given away to anyone who wishes to take it, without any need to ask me first. I do not wish to retain a co-maint either, so please just go ahead and transfer the ownership :) Thanks!


Today's Thursday, and if you regularly read blogs.perl.org, you know today is the first day of my plan to combat bit rot.

Happy Bit Rot Thursday, everyone!

The first step I'm undertaking is reducing the number of projects under my wing by means of deleting them entirely or putting them up for adoption. In total, there are about 107 modules I made adoptable, although some of them are a bundle deal.

Adoption

Here are adaptable modules that I moved to the ADOPTME user. If interested, you should be able to claim any of them by emailing PAUSE admins at modules at perl dot org and asking them to transfer permissions to you. See neilb's blog post for more details.

I do realize a lot of them are trash, even if some were useful or amusing back when I first started coding Perl. I don't think I'd cry if I find out some of them get deleted by adopters.

And the modules are:

Deletion

Also, some modules went under the axe and have been marked for deletion:

  • Acme::Excuse — a useless modules that intercepted __DIE__ signal and showed a random message from http://www.programmerexcuses.com/
  • Acme::XAppender — the "x appender framework" that resulted from a joke in a #perl IRC channel
  • App::IRCBot::NewYears — a bot for IRC New Years parties. While I still plan to make my bot attend such parties, it'll now be the Perl 6 version
  • Package::Localize — a half-working module that lets you use multiple different copies of packages with package-scoped variables. In the end, it didn't work out for my purpose.

In Perl 6 land, I removed these:

More

What I've done today is not all the modules I wish to delete or give away. Those I've left for the next time need evaluation to see whether anything uses them. Also, as I become more and more interested in programming Perl 6, rather than Perl 5, there may come a day, when I give all of my Perl 5 goodies up. Only time will tell.

Bit Rot Thursday

Part 1: There is a Problem

I don't think I'd have to look for long for someone who'd agree that writing new code is much more fun that fixing bugs in old one. A cool new idea gets written up, while older code is still lacking tests. A new module gets shipped, while there's still that API improvement proposal from 6 months ago in the other. And while you're drafting a design document for the Next Awesome Thing, the rest of your code is being slowly consumed by bit rot.

Having written 250–300 Perl 5 modules and now 32 Perl 6 modules and other ideas, I'm more than aware of what it feels like to be leaving a decaying pile of code in your wake. The problems I notice are these:

  • Unfixed bugs
  • Lack of compresensive tests
  • Lack of documentation
  • Bad documentation (too wordy; incorrect; partial)
  • Unimplemented new features, even if the proposal for them was approved
  • Partial implementation (an FTP client that can only download, for example)

I can think of several reasons why it might be hard to find motivation to take care of bit rot, all of which are perfectly valid:

  • You're "too busy." You spent 8 hours at work, hacking on arcane code, and when you come home you want to relax and play Warframe and not spend 3 more hours hacking on arcane code. Your next Killer App is more important than this module you wrote 5 years ago because you were bored. Your interests changed: you no longer do web development with Perl 5 and instead are hacking on Artificial Intelligence software with Perl 6. And maybe you just have too many projects in the first place.
  • You don't know what needs to be done. Sure, CPAN Testers send you emails when something's broken, but it's easy to put off until the mythical "tomorrow." Your documentation is missing and users want new features, but you forgot that was brought up a few months ago. And what about Issues that go stale without any plan of action?
  • It's too hard. You set out to do a task and you implemented A, B, and C. Now, someone came up to you and said your thing is lacking X. Problem is, you don't have adequate knowledge and experience to implement X. And learning it requires both time and interest. Another example: users are reporting a nasty bug, but you can rarely reproduce it, and when you do, you still have no idea why it occurs.

And while entropy is a tough foe to conquer, I think at least acknowledging there is a problem is a good stepping stone to finding a workable solution.

Part 2: There is a Solution

I toyed with the idea of dedicating a special day to deal with just these sort of problems for a while. Today, I decided to commit myself to it, and I invite anyone willing, to do so themselves and address bit rot in their own software. The plan is simple:

Every Thursday is a "Bit Rot Thursday." You find some time to address bit rot and just do it. Why Thursday? I figure Friday, Saturday, and Sunday are all about relaxing; Monday, Tuesday, Wednesday are a beginning of the week people tend to "hate"; and Thursday is in the sweet spot: do work just before the weekend and feel good about yourself when the weekend comes. Since monotony is boring, you get one Thursday every month that you can "legally" skip and do nothing. Keep in mind, Bit Rot Thursday is not only about dealing with current bit rot, but doing preventative care as well. Let's see how we can accomplish those goals:

Toss It in the Bin

Before you rush off to fix a bug in your lolcat_phrase_generator_5000.pl, ask yourself: is this script or module still needed? You may feel attached to this "web framework" you wrote 8 years ago, but nobody—even you any more—uses it, so implementing HTTP/2 in it is likely a waste of time.

The modules you delete off CPAN will still be available on BackPAN, so don't be shy. You only have this much time in a day, and it's necessary to regularly throw clutter out. This is quite equivalent to accumulating useless trinkets in your garage, in case you'll need them some day. Just toss it in the bin.

Give It Away

If you don't think your software deserves such a harsh fate as being wiped from the face of Earth, consider putting it up for adoption. You can use blogs, social media, and IRC to advertise that you're looking for a new maintainer who'd be interested in fixing issues. On CPAN, you can transfer the module to user ADOPTME, to enlist your module as adoptable by interested parties. Perl 6 has its own version of the idea: place the META file into the SHELTER and then remove your module from the Ecosystem.

Delegate

Instead of parting with your goods completely, delegate. The Mojolicious project is a good example of how to seek out volunteers: Issue labels future and help wanted are used to indicate work to be done and social media is used to advertise and find volunteers willing to do the required work.

Did someone submit a report for a bug? Ask the submitter whether they'd be able to fix it. Did someone request a new feature? Suggest you'd accept a patch. Include details on what you think might be causing the bug and outline the details of how a feature can be implemented. Even if that person is unable to help, you'll have a plan of action already in writing.

Find and Review Reports

Go through RT tickets, GitHub Issues, your notes and reminders. When you log in to RT, the Bugs in My Distributions panel is third on the left. On GitHub, click the Issues link in top, center of the page and then change author: to user: in the search box. This will show you all open Issues in your code. You can use user: more than once, if you wish to also include issues from GitHub organizations you belong to. As an example, here's a search query that shows both Issues in my code and in Perl 6 organization: is:open is:issue user:zoffixznet user:perl6

Get a MetaCPAN account and try out the Dashboard MetaCPAN Lab to see the number of open issues and test failures in all your modules: https://metacpan.org/lab/dashboard.

Categorize the issues using tags and labels. Merge duplicates. Close anything that's irrelevant, can't or won't be fixed. If the conversation died out, just close the ticket with a request to reopen it if anyone has the same issue. There's no reason for tickets to be left open for years.

Evaluate Unreported Things

Go to CPAN Testers and browse by Author to your Author page (middle of page, third section). You can then use the Preferences panel on the left to generate a link to show failures only. Bookmark it. Examine any failures and see if you can fix them. When you upload new modules, if their tests are failing, you should be getting an email from CPAN Testers informing you there is a problem. If you're not getting those, check your settings and your spam folder.

Use Devel::Cover to evaluate how well your tests cover your code. If you use Dist::Zilla, there's Dist::Zilla::App::Command::cover that adds cover command to dzil.

To ensure your documentation is complete, add Pod::Coverage to your author tests (that is, place it in xt/ directory rather than t/ so it doesn't run during user's installation). Completeness is one thing, but quality is another. Examine your extant documentation. Try to reduce the amount of words in it, while still retaining information. Use examples! A good, clear example can shave off a whole paragraph of dense technical text. There's nothing wrong with actively inquiring your users about the quality of the documentation. Do people frequently ask a particular question? Creating a FAQ is one way to go, but it's often an indicator your actual documentation can be improved in that area.

In Perl 6, Test::META lets you find problems in your META file and Pod::Coverage distribution includes Test::Coverage module to check completeness of your docs.

Prevent Bit Rot

So far, our Bit Rot Thursday sounds mundane and boring, dealing with tedious problems. However, you can actively work against those problems appearing in the first place.

When you start a new project, do you write down a clear definition of the problem you're attempting to solve? A sure-fire way to waste time is to spend several days adding a ton of configuration options and features that you don't have any use for, simply because you never defined a concrete problem to solve. Worse: you continue to support and maintain all those features for years to come!

When you lay down the first line of code, do you have some form of a "spec" that details the bits and pieces of your project and how they're supposed to interact with each other? I'll leave it to other sources to argue for cost savings of such an approach, but I can tell you that when you realize JSON and not PDF is better suited for the output of your program, rewriting two paragraphs of text in the spec is much simpler than rewriting several subroutines, methods, and tests.

A design spec also makes it much easier to create both tests and user documentation for your project. The test suite is the spec translated into a computer language. The docs are the spec with internal details removed and code examples added.

Speaking of tests, it's often handy to write them first, before your actual module or script. The tests define the problem you're attempting to solve. Failing tests indicate what bits you haven't solved yet. You can also very easily track your progress, as you can see how many tests still fail. Since this approach generates a lot of output on each test run, you may find Test::Most's DIE_ON_FAIL useful. You can include it in code or use DIE_ON_FAIL=1 environmental variable and this will cause the test suite to stop at the first failure.

So spend your Bit Rot Thursday making templates for specs and tests and outlining plans for what sort of documents need to be prepared for the types of projects you create. It's also a good idea to draft up guidelines for contributors, to make it clearer what sort of contributions you're looking for. You'll spend less time explaining your standards in pull requests!

Growing Yourself

Who is more likely to produce a wall that'll crumble in a year: an experienced bricklayer or a novice? Writing code certainly gives you practice, but you need theory too, as well as to keep yourself up to date with the world. You can write a million lines of code that uses CGI.pm and memorize every word in its documentation, but in 2016 you'll still be unemployable in the field of Web Development if that's all you can do. Technologies change. Standards change. Practices change. We should change too.

And so, it's possible to spend the Bit Rot Thursday away from the keyboard. On a train, plane, bus, or boat, with your phone or tablet, reading programming blogs and articles. At a bar with your fellow programmers, exchanging ideas. In a park, on a sunny day, with a programming book in your hand.

And as you get better, so will your code...

Perl 6 is written in... Perl 6

Today, I've done something strange.

No, there weren't drugs involved, I merely sent a patch for Rakudo for a bug I reported a few weeks back. But the patch is... interesting.

First, about the "bug." Newest JSON spec lets you have anything as the top level thing. I spotted a few modules in the Perl 6 ecosystem that still expected an object or an array only, and the vendor-specific (possibly to be made hidden in the future) to-json subroutine provided by core Rakudo behaved the same as well.

One of the modules got fixed right away and today, seeing as there were no takers, I went in to fix the bug in Rakudo myself. Since I'm a lazy bum, I merely went in to that one fixed module and just copied the fix over!

But wait a second... ain't the Perl 6 module written in Perl 6? How did I manage to "just copy it over"? What sorcery is this! Surely you lie, good sir!

Here are the Rakudo and the module patches one above the other. Try to figure out which one is for Rakudo:

source2.png

Give up yet? The code above the black bar is the patch made in JSON::Tiny module and the code below it is the patch I made for Rakudo.

As surprising and amazing as it is, most of Perl 6 is actually written in Perl 6! The NQP (Not Quite Perl) provides the bricks and the mortar, but when it comes to the drywall, paint, and floorboards, you're full in the Perl 6 territory.

So what does this all mean?

I'm not a genius programmer and I'm quite new to Perl 6 too, but I was able to send in a patch for the Perl 6 compiler that fixes something. And it's not even the first time I sent some Perl 6 code to improve Rakudo. Each one of the actual users of Perl 6 can fix bugs, add features, and do optimizations. For the most part, there's no need to learn some new arcane thing to hack on the innards of the compiler.

Imagine if to fix your car or to make it more fuel efficient, all you had to do was learn how to drive; if to rewire your house, all you had to do is learn how to turn on TV or a toaster; if to become a chef, all you had to do was enjoy a savory steak once in a while. And not only the users of Perl 6 are the potential guts hackers, they also have direct interest in making the compiler better.

So to the speculations on the potential Perl 6 Killer App, I'll add that one of the Perl 6's killer apps is Perl 6 itself. And for those wishing to add "programming a compiler" onto their résumés, simply clone the Rakudo repo and go to town on it... there are plenty of bugs to squish.

Python is The New "Write-Only, Linenoise" Language

As a Perl 5 programmer of about a decade, I'm well aware of how it was referred to at some point or another as the "write-only" and "linenoise" language. With the newest addition of the baby Perl 6 language to the Perl family, I fear that I must declare (wildly speculate) based on my extensive research (a boring ride on a bus, while staring at my phone) that Python steals that title now!!

Why Python? Blame whoever made the Stackoverflow Python Report scroll through my Twitter feed. I merely picked two problems from that list and asked myself what would the Perl 6 solutions to them look like.

Interleave Two Strings

The top rated item of the week is interleaving two strings.

#Given:
u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'

#Wanted:
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

The accepted Python answer is this:

res = "".join(i + j for i, j in zip(u, l))
print(res)

Certainly isn't bad, but using a two-variable postfix for loop inside a method call is something I wouldn't want to read in code very often. Let's examine the Perl 6 version:

say join '', (u.comb Z l.comb)

Just like the Python version, we're utilizing the join(), but the rest looks certainly cleaner: we're using the .comb method on our two strings, which without arguments returns characters in a string, and we combine them with the Z zip operator. That is it! No loops needed. (And before someone points it out, no, I haven't missed any sigils. Perl 6 can have sigilless vars, baby).

Round-Robin Merge Two Lists of Different Length

Another interesting item on the list is round-robin merge of two different-length lists. There isn't an accepted answer to the question, so I'll go with the highest-voted:

list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
list2 = ['x', 'y'] 
n = 3

iter1 = iter(list1)
res = []
for x in list2:
    res.extend([next(iter1) for _ in range(n - 1)])
    res.append(x)
res.extend(iter1)

>>> res
['a', 'b', 'x', 'c', 'd', 'y', 'e', 'f', 'g', 'h']

I see a for loop, and another for loop, .extend method and then .append method and after another .extend after the outer for loop, voilà! Result.

Being a Perl 6 noob, I first reached for the trusty Z operator, then I messed with the Hyper Operators, and all I got in return were either wrong solutions or messy solutions... Until someone pointed out that Perl 6 actually has a roundrobin routine! So what's the Perl 6 answer?

my @list1 = 'a' .. 'h';
my @list2 = <x y>;
say flat roundrobin @list1, @list2;

# >>>
# OUTPUT«a x b y c d e f g h»

On the first two lines, we're simply creating two variables for our lists. @list1 uses a range with letters and @list2 uses the quote word construct. I'm sure similar things exist in Python too, so I won't count clarity and ease-of-writing points for those, but the rest of the code is rather different. There are no loops, extends, or appends. We use the roundrobin routine to... surprise... round-robin through the two lists. Now, it returns a Seq of Lists, which is why I added the flat routine as well, to flatten the output to what the Python answer returns.

EDIT: as one of the commenters pointed out, I wasn't paying much attention to this one and completely missed the "nth element" requirement. Never fear, however, the alternate requirement only needs the addition of trusty .rotor List method that breaks up a list into sublists:

my @list1 = 'a' .. 'h';
my @list2 = <x y>;
my $n = 3;
say flat roundrobin @list1.rotor($n - 1, :partial), @list2;

# >>>
# OUTPUT«a b x c d y e f g h»

Summary

This post is, of course, a tongue-in-cheek joshing, based on a random post I saw on Twitter. However, on a more serious and deeper note, it does seem that the brand-new language like Perl 6 that has an actual language specification, when compared to an old grandpa specless language like Python, seems to offer built-in methods, operators, and subroutines specifically geared to real-world problems that—for however short a period of time—made it to the top of a popular programming question website.

And now, if you'll excuse me, I'm off to make a silly YouTube video declaring Python to be the new "Write-only, Linenoise" language. Sorry, Perl. You lose.

Update 1

As I'm not the one to shyly sit in a silo, I went to #python on irc.freenode.net and asked for feedback on this article, and it's this:

In the first example, the use of the for loop is extremely idiomatic Python, so the code is perfectly readable to a competent Python programmer. As for the second Python example, the general opinion was that it's overly-complex and I did see a simple 1-line round-robin example presented to me in-channel. The nth element variant may be dropped to me on Twitter as well in the future :)

I stayed for some drinks, there was cake too! And then I left the channel...

The Perl 6 User Experience

A person's experience with a programming language involves many aspects: how a user first learns that a language exists, their first steps in that language, their process of learning more about it, developing in it, contributing to it, and spreading the word about it are all part of that experience. In short, it's a huge swath of elements, which is why it's important to have a means to efficiently identify any issues in that experience, so that it can be improved.

I'd like to announce the creation of The Perl 6 User Experience Repository. Its main page enumerates various aspects of the Perl 6 User Experience and the sub-pages will outline plans to overcome any of the identified problems, or perhaps serve as a documentation repository for protocols, lists of contacts, or other additional files.

A valuable aspect of that repository is the Issues tab where anyone can bring up an issue with any aspect of the Perl 6 User Experience, for possible consideration and improvement. A set of Issue labels corresponding to main sections listed on the main page has been created, so the Issues can be tagged approprietly.

Having a centralized place to raise such issues should prove more useful than an occasional grumble on an IRC channel, a blog post, or a Reddit comment. Those things tend to slip through the cracks and get forgotten.

Main Sections

Here are the main sections currently available. At the moment, they're the result of one mind's work, and thus I fully expect changes: more sections added, sections removed, changed, or expanded. PRs are welcome.

Finding Out Perl 6 Exists

The rest of the User Experience can never exist if no one knows Perl 6 exists. Are there any issues that need to be addressed when it comes to people finding out Perl 6 is a thing? Do the marketing materials deliver their point? Do blog articles, social media posts, and news items about Perl 6 ever reach the ears and eyeballs of those who aren't familar with Perl 6?

Getting Perl 6

Once interest sparks up, how does a person get to the point where they can run some Perl 6 code and have it work? If they care, can the person understand the difference between, say, Perl 6.c the language, Rakudo 2015.12 the compiler, and Rakudo Star the distribution? And if they don't care, is it still easy for them to "install Perl 6"?

At the time of this writing, this is a section where a definite problem has been identified and a plan of action has been put in place.

Running Perl 6

Installation is just one step. How easy is it for a user to run a Perl 6 program? Such a program may require the functionality offered by a module in the Ecosystem. Is the search feature functional enough to find such a module? Is the toolchain usable enough to correctly install that module?

Developing in Perl 6

A Perl 6 programmer produces modules and programs. Is there a toolset available to simplify that process (e.g. a dist-minting toolkit like Dist::Zilla in Perl 5)? Is it easy to package a Perl 6 program so that it can be sold to a customer or deployed by someone not knowledgeable about Perl 6?

Getting Help and Training

Efficiently programming in Perl 6 is tough if you can't get help when you run into issues or don't receive proper training. Do Perl 6 and its ecosystem modules offer useful and complete documentation? Do Perl 6 users know where to ask for help? Can they easily access those channels, even if they don't have experience with things like, say, IRC? Is it easy for them to find out about and attend Perl 6 conferences and workshops?

Reporting Problems

If a user has any issues with Perl 6 or its compilers or modules, or even something else, how easy is it for them to report those problems? Will they get notified when the reported problems get resolved?

This is an area where The Perl 6 User Experience Repository itself falls under and can itself have issues to be addressed.

Contributing to Perl 6

Should a user wish to give back to the Perl 6 community, how easy is it for them to find out what needs to be done and to contribute their work? Is it easy for them to get commit bits, if their work is of stellar quality? Do contributors get proper recognition?

Interacting with the Community

A strong community doesn't just talk code all the time. They chat about other things and go out for a drink. Is that available in a Perl 6 community?

Are there any community participation barriers—whether deliberate or accidental—for persons of a particular gender, sexual orientation, race, age, creed, nationality, or physical, mental, or technical abilities?

Is there a Standard of Conduct that sets the bar for the expected way the members of the Perl 6 Community treat others? Is there a particular person one can safely contact in private, when that Standard of Conduct is violated, or when other members of the community are being abusive?

Being a Perl 6 Programmer

The last section completes the circle the first section started. A Perl 6 Programmer exists in a larger world and tells that world about Perl 6; whether it is by working at a job that involves Perl 6, by interacting with communities of other languages, or by simply spreading the word about Perl 6 on blogs, social media, and conferences.

Are there resources allowing to post or search for Perl 6 job offerings? Are there any issues with other communities? Do Perl 6 markerting materials—like printable brochures or a well-written "sales pitch"—exist and is it easy to obtain them? Is there Perl 6-styled merchandize, like mugs, pens, or shirts, one could either get to keep for themselves or to hand out at some event? Are there places someone can blog about Perl 6, if they don't have a blog space of their own?

The Frustrated Reporter

The nature of what this repository wishes to address begs an obvious question: won't we end up with a whole bunch of low-quality Issues created by frustrated users banging on their keyboards while foaming at the mouth?

Well, we probably will. If I spent "three f#$(!ng hours" trying to install a Perl 6 compiler just to get "this stupid script" to run, I'll be quite angry, I'll use colourful terms in the Issue I create, and I'll likely blame the creators of whatever I tried to use for my frustration. Those responding to such Issues must be aware of where The Frustrated Reporter is coming from. Something made that user this aggravated and it's possible that something can be improved.

"So little time, so many things undone..."

The Perl 6 User Experience covers a lot of things. Big things. Huge things! I suspect most Issues won't be closed with a simple and quick one-line fix. Some will require an extra army of Volunteers. This is what this blog post—and, indeed, the repository itself—is all about: inviting people to pitch in. Not only to report the issues, but to attempt to resolve them, and... to become a part of The Perl 6 User Experience itself.

Why in The World Would Anyone Use Perl 6?

I mean, can you get it any more WRONG?! The juvenile logo and awful color scheme of the website. The Christmas release that isn't all release-like. Version 6.c? Why not 6.0? What's with the whole "language" and "compiler" distinctions no one cares about? Why is the first stable release of the compiler not optimized to the max? And why is it called "Perl" in the first place? They should rename it!!

Too little, too late. Is there a need for a new Perl? No, of course not. What is it good for? Nothing. What is its business case? None! What's Perl 6's "Killer App"? Non-existent. Why in the world would anyone use Perl 6?!

In the three short months since I joined the Perl 6 community, those are some of the criticisms and attacks I had to endure—and sometimes respond to—on blogs, HackerNews, IRC, and Twitter.... I don't mind it at all, since there's little substance in those attacks. At the end of the day, I'm just writing my Perl 6 code. Enjoying it a lot, too.

Am I not meant to?

Must I look for logos tailored to the 50-something CIOs and not logos aiming to discourage misogyny in the community, before I even try the language? Must I demand the first stable release of something to perform better than other things that had a couple of decades of optimization? Must I demand from volunteers they spend the Holidays making a picture-perfect release instead of enjoying rest with their families? Must I hold every open-source tool I use to such standards? A solid, clear business case or GTFO?

cowsay.png

English isn't my native language. That language is something else and I can barely speak it now. Don't have much use for it. In fact, I dislike it. It's nothing major—some of the most famous literature in the world is written in that language, after all—but... well... it's the little things.

Maybe it's having too many letters or weird letters that aren't usually present on a keyboard. Maybe there are too many rules and too many special cases for them too! Maybe... Ugh, the language is just ugly, you know? I want results and not a language.

Of course, the same applies to programming languages too. It's the little things. Like having to write foo(1, 2, 3) instead of foo 1, 2, 3; or writing some_var instead of some-var; importing a lot of functionality instead of having it available from the get-go; perhaps writing if 5 < x and x < 100 instead of the much clearer if 5 < $x < 100; or how about checking a set contains only valid elements? In Perl 6, it's just a set operator away: if @given ⊆ @valid; or use subsets and junctions! I want results and not a language.

Omited parentheses and fancy operators are little things, I know. But they add up. Some programs that I converted to Perl 6 are nearly half the original size. In a 100,000-line program, that's 50,000 lines you don't have to write, and, especially, read later.

And it's things like these that make me enjoy programming in Perl 6. It's this that makes me feel—once again—the wonder I experienced 16 years ago, when I wrote my first program: writing something simple and getting the result, as if by magic. It's hackers like me who will nurture Perl 6 and help her grow. The trailblazers. The unabashed. We stare in the face of critique without flinching. We use the tools with value, not ones with solely a marketing campaign. We'll build the ecosystem and the killer apps. And should you decide to give our tool a spin and should you like it, we'll welcome you with open arms.

Why in the world would anyone use Perl 6? Well... it's the little things.

About Zoffix Znet

user-pic I blog about Perl.