<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/" ><channel>
    <title>Perlgeek.de   </title>
    <link>http://perlgeek.de/blog-en/</link>
    <description>Perl and Programming Blog.</description>

  <item>
 <title>Perl 6 Coding Contest 2019: Seeking Task Makers</title>
  <link>http://perlgeek.de/blog-en/perl-6/2018-perl6-coding-contest-seeking-task-makers.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Sat, 10 Nov 2018 23:00:01 +0100</pubDate>
    <description>&lt;!-- 2018-11-11 --&gt;

&lt;p&gt;I want to revive &lt;a href=&quot;http://strangelyconsistent.org/blog/masaks-perl-6-coding-contest&quot;&gt;Carl Mäsak's Coding Contest&lt;/a&gt;
as a &lt;a href=&quot;https://gist.github.com/moritz/6f06ec7153ce396ac2734c2616d8b075&quot;&gt;crowd-sourced contest&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The contest will be in four phases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;development of tasks&lt;/li&gt;
&lt;li&gt;public contest, where you can solve the tasks&lt;/li&gt;
&lt;li&gt;public commenting on solutions&lt;/li&gt;
&lt;li&gt;grading and awarding of prizes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the first phase, development of tasks, I am looking for volunteers who
come up with coding tasks collaboratively. Sadly, these volunteers, including
myself, will be excluded from participating in the second phase.&lt;/p&gt;

&lt;p&gt;I am looking for tasks that ...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;are well-worded&lt;/li&gt;
&lt;li&gt;have a (private) implementation that shows it is solvable, preferably
in under 500 lines of code&lt;/li&gt;
&lt;li&gt;have a few public tests to help the participants, and a more tests
tests that help the graders and commenters later on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is non-trivial, so I'd like to have others to discuss things with,
and to come up with some more tasks.&lt;/p&gt;

&lt;p&gt;If you want to help with task creation, please send an email to &lt;a href=&quot;mailto:moritz.lenz@gmail.com&quot;&gt;moritz.lenz@gmail.com&lt;/a&gt;, stating your intentions to help, and your freenode IRC handle (optional).&lt;/p&gt;

&lt;p&gt;There are other ways to help too:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can pledge a prize (some ideas: &lt;a href=&quot;https://commaide.com/&quot;&gt;Comma IDE&lt;/a&gt; subscription,
books, Camelia plushies, Amazon vouchers)&lt;/li&gt;
&lt;li&gt;You can help design a small website for the contest&lt;/li&gt;
&lt;li&gt;You can help iron out the exact rules for the contest&lt;/li&gt;
&lt;li&gt;... or any other way that I didn't think of :-)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In these cases you can use the same email address to contact me,
or use IRC (&lt;code&gt;moritz&lt;/code&gt; on freenode) or &lt;a href=&quot;https://twitter.com/nogoodnickleft&quot;&gt;twitter&lt;/a&gt;.&lt;/p&gt;




</description>
  </item>
  <item>
 <title>My Ten Years of Perl 6</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-020-ten-years.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Tue, 08 Aug 2017 22:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-08-09 --&gt;

&lt;p&gt;Time for some old man's reminiscence. Or so it feels when I realize that
I've spent more than 10 years involved with the Perl 6 community.&lt;/p&gt;

&lt;h2&gt;How I Joined the Perl 6 Community&lt;/h2&gt;

&lt;p&gt;It was February 2007.&lt;/p&gt;

&lt;p&gt;I was bored. I had lots of free time (crazy to imagine that now...), and I spent some of that answering
(Perl 5) questions on perlmonks. There was a category of questions where
I routinely had no good answers, and those were related to threads. So I
decided to play with threads, and got frustrated pretty quickly.&lt;/p&gt;

&lt;p&gt;And then I remember that a friend in school had told me (about four
years earlier) that there was this
Perl 6 project that wanted to do concurrency &lt;em&gt;really&lt;/em&gt; well, and even
automatically parallelize some stuff. And this was some time ago, maybe
they had gotten anywhere?&lt;/p&gt;

&lt;p&gt;So I searched the Internet, and found out about Pugs, a Perl 6 compiler
written in Haskell. And I wanted to learn more, but some of the links to
the presentations were dead. I &lt;a href=&quot;https://irclog.perlgeek.de/perl6/2007-02-04#i_-55445&quot;&gt;joined the #perl6 IRC channel to report
the broken link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And within three minutes I got a &quot;thank you&quot; for the report, the broken
links were gone, &lt;em&gt;and&lt;/em&gt; I had an invitation for a commit bit to the
underlying SVN repo.&lt;/p&gt;

&lt;p&gt;I stayed.&lt;/p&gt;

&lt;h2&gt;The Early Days&lt;/h2&gt;

&lt;p&gt;Those were they wild young days of Perl 6 and Pugs. Audrey Tang was
pushing Pugs (and Haskell) very hard, and often implemented a feature
within 20 minutes after somebody mentioned it. Things were unstable,
broken often, and usually fixed quickly. No idea was too crazy to be
considered or even implemented.&lt;/p&gt;

&lt;p&gt;We had bots that evaluated Perl 6 and Haskell code, and gave the result
directly on IRC. There were lots of cool (and sometimes somewhat
frightening) automations, for example for inviting others to the SVN
repo, to the shared hosting system (called feather), for searching SVN logs
and so on. Since git was still an obscure and very unusable, people
tried to use &lt;a href=&quot;https://en.wikipedia.org/wiki/SVK&quot;&gt;SVK&lt;/a&gt;, an attempt to
implement a decentralized version control system on top of of the SVN
protocol.&lt;/p&gt;

&lt;p&gt;Despite some half-hearted attempts, I didn't really make inroads into
compiler developments. Having worked with neither Haskell nor compilers
before proved to be a pretty steep step. Instead I focused on some
early modules, documentation, tests, and asking and answering questions.
When the IRC logger went offline for a while, I wrote my own, which is
still in use today.&lt;/p&gt;

&lt;p&gt;I felt at home in that IRC channel and the community. When the community
asked for mentors for the Google Summer of Code project, I stepped up.
The project was a revamp of the Perl 6 test suite, and to prepare for
mentoring task, I decided to dive deeper. That made me the maintainer of
the test suite.&lt;/p&gt;

&lt;h2&gt;Pet Projects&lt;/h2&gt;

&lt;p&gt;I can't recount a full history of Perl 6 projects during that time
range, but I want to reflect on some projects that I considered my pet
projects, at least for some time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In early 2008 I started to contribute some patches to
&lt;a href=&quot;https://perl6.org/&quot;&gt;perl6.org&lt;/a&gt;. Over time I became frustrated with
the outdated content on many Perl 6 websites, so I created
perl6-projects.org, which only contained links to up-to-date
resources. Over time, people with an actual sense of design contribute
a nice layout. Later we switched perl6.org over to the content from
perl6-projects.org. Its structure today is still mostly that of a link
collection.&lt;/li&gt;
&lt;li&gt;In September 2008 I started with the &lt;a href=&quot;https://perlgeek.de/en/article/5-to-6&quot;&gt;Perl 5 to
6&lt;/a&gt; blog series, which was the
de facto resource for learning Perl 6 for some years.&lt;/li&gt;
&lt;li&gt;In 2009 I wrote &lt;a href=&quot;https://github.com/moritz/json/&quot;&gt;JSON::Tiny&lt;/a&gt;, the
first pure-Perl 6 JSON parser. I mostly did it to become familiar with
grammars, and because the book &quot;Real World Haskell&quot; also developed a
JSON module.&lt;/li&gt;
&lt;li&gt;May 2010 kicked off a program to make &lt;a href=&quot;https://perlgeek.de/blog-en/perl-6/contribute-now-announce.html&quot;&gt;contributing to Perl 6 more
accessible&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;September 2010: the Pugs SVN repository became unmaintainable. It had
accumulated the official Perl 6 test suite, some documentation,
modules, at least one IRC bot and a proverbial metric ton of other
stuff. In coordination with #perl6, I split it up into a collection of
git repositories and put them on GitHub. A decision we haven't
regretted yet. &lt;/li&gt;
&lt;li&gt;In 2012 and 2016 I was part of the organization team of the German
Perl Workshop in Erlangen and Nürnberg, which both featured several
Perl 6 talks.&lt;/li&gt;
&lt;li&gt;2012 saw the birth of &lt;a href=&quot;https://docs.perl6.org/&quot;&gt;the documentation
project&lt;/a&gt;. Initially I was nearly the sole
contributor, and I'm very happy that, over time, others have taken over.&lt;/li&gt;
&lt;li&gt;Between 2014 and 2015, our community server &quot;feather&quot; EOLed, so the
Perl 6 community &lt;a href=&quot;https://perlgeek.de/blog-en/perl-6/2014-community-server-funding.html&quot;&gt;funded a new
server&lt;/a&gt;,
which my &lt;a href=&quot;https://www.noris.de/&quot;&gt;employer, noris network AG&lt;/a&gt; kindly
hosts for free in their data center in Nürnberg, Germany.&lt;/li&gt;
&lt;li&gt;In 2016 I started writing &lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;Perl 6 by Example&lt;/a&gt;,
which Apress later adopted and published as &lt;a href=&quot;https://www.apress.com/us/book/9781484228982&quot;&gt;Perl 6
Fundamentals&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Currently I'm working on a treatise on &lt;a href=&quot;https://leanpub.com/perl6regex&quot;&gt;Perl 6 Regexes and
Grammars&lt;/a&gt;, which Apress will also
publish.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is not quite clear from this (very selected) timeline, but my Perl 6
related activity dropped around 2009 or 2010. This is when I started to
work full time, moved in with my girlfriend (now wife), and started to
plan a family.&lt;/p&gt;

&lt;h2&gt;Relationships&lt;/h2&gt;

&lt;p&gt;The technologies and ideas in Perl 6 are fascinating, but that's not
what kept me. I came for the technology, but stayed for the community.&lt;/p&gt;

&lt;p&gt;There were and are many great people in the Perl 6 community, some of
whom I am happy to call my friends. Whenever I get the chance to attend
a Perl conference, workshop or hackathon, I find a group of Perl 6
hackers to hang out and discuss with, and generally have a good time.&lt;/p&gt;

&lt;p&gt;Four events stand out in my memory. In 2010 I was invited to the Open
Source Days in Copenhagen. I missed most of the conference, but spent
a day or two with (if memory serve right) Carl Mäsak, Patrick Michaud,
Jonathan Worthington and Arne Skjærholt. We spent some fun time trying
to wrap our minds around macros, the intricacies of human and computer
language, and Japanese food. (Ok, the last one was easy). Later the same
year, I attended my first YAPC::EU in Pisa, and met most of the same
crowd again -- this time joined by Larry Wall, and over three or four
days. I still fondly remember the Perl 6 hallway track from that
conference. And 2012 I flew to Oslo for a Perl 6 hackathon, with a
close-knit, fabulous group of Perl 6 hackers. Finally, the &lt;a href=&quot;http://blogs.perl.org/users/liz/2012/08/as-some-of-you-may.html&quot;&gt;Perl
Reunification
Summit&lt;/a&gt;
in the beautiful town of Perl in Germany, which brought together Perl 5
and Perl 6 hackers in a very relaxed atmosphere.&lt;/p&gt;

&lt;p&gt;For three of these four events, different private sponsors from the Perl
and Perl 6 community covered travel and/or hotel costs, with their only
motivation being meeting folks they liked, and seeing the community
and technology flourish.&lt;/p&gt;

&lt;h2&gt;The Now&lt;/h2&gt;

&lt;p&gt;The Perl 6 community has evolved a lot over the last ten years, but it is
still a very friendly and welcoming place. There are lots of &quot;new&quot; folks
(where &quot;new&quot; is everybody who joined after me, of course :D), and a
surprising number of the old guard still hang around, some more
involved, some less, all of them still very friendly and supportive&lt;/p&gt;

&lt;h2&gt;The Future&lt;/h2&gt;

&lt;p&gt;I anticipate that my family and other projects will continue to occupy
much of my time, and it is unlikely that I'll be writing another Perl 6
book (after the one about regexes) any time soon. But the Perl 6 community
has become a second home for me, and I don't want to miss it.&lt;/p&gt;

&lt;p&gt;In the future, I see myself supporting the Perl 6 community through
infrastructure (community servers, IRC logs, running IRC bots etc.),
answering questions, writing a blog article here and there, but mostly
empowering the &quot;new&quot; guard to do whatever they deem best.&lt;/p&gt;



</description>
  </item>
  <item>
 <title>Writing a Systemd Supervised Service with Perl</title>
  <link>http://perlgeek.de/blog-en/perl-tips/2017-systemd-supervised-daemon-perl.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Mon, 24 Jul 2017 22:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-07-25 --&gt;
&lt;p&gt;There are many ways in which server software can fail.
There are crashes, where the server process exits with an
error. Program supervisors can catch those easily, and you
can monitor for the presence of a server process.&lt;/p&gt;

&lt;p&gt;But recently I had to deal with some processes that
didn't just crash; they got stuck. It happens only rarely,
which makes debugging harder. It involves AnyEvent, forking,
the boundaries between synchronous and asynchronous code,
and runloops getting stuck. I know the problem needs a much
deeper solution, which will take weeks to implement.&lt;/p&gt;

&lt;p&gt;So, there was a need for a much faster approach for at
least detecting the stuck service, and possibly even restart
it. And even if the problem was fixed, some monitoring
wouldn't hurt.&lt;/p&gt;

&lt;h2&gt;Heartbeats&lt;/h2&gt;

&lt;p&gt;The standard approach to checking the aliveness of a
process (or a connection) is a heartbeat. A heartbeat is a
periodic action that a process performs; if the process
fails to perform that action, a supervisor can pick up on
that cue, and do an appropriate action. The action can be
restarting the process, closing a TCP connection or so.&lt;/p&gt;

&lt;p&gt;So, for a server process, what's a good heartbeat? The
most basic approach is writing to a log file, or touching a
file. The supervisor can then check for the
up-to-dateness.&lt;/p&gt;

&lt;h2&gt;Systemd and Heartbeats&lt;/h2&gt;

&lt;p&gt;Since I already used Systemd for managing the service, I
wanted to see if systemd supported any heartbeats. It does,
and &lt;a
href=&quot;https://superuser.com/questions/689017/can-systemd-detect-and-kill-hung-processes&quot;&gt;this
superuser post gives a great overview&lt;/a&gt;. In the context of
systemd, a watchdog needs to call the &lt;a
href=&quot;https://freedesktop.org/software/systemd/man/sd_notify.html&quot;&gt;sd_notify&lt;/a&gt;
C function, which seems to live in the libsystemd.so
library. This communicates through some mysterious,
unknowable mechanism (actually just a UNIX socket) with systemd. To allow that 
communication channel, the systemd unit file must include
the line &lt;a
href=&quot;https://freedesktop.org/software/systemd/man/systemd.service.html#NotifyAccess=&quot;&gt;NotifyAccess=main&lt;/a&gt;,
which allows the main process of the server to communicate
with systemd, or &lt;code&gt;NotifyAccess=all&lt;/code&gt;, which allows
subprocesses to also use &lt;code&gt;sd_notify&lt;/code&gt;.&lt;/p&gt;


&lt;p&gt;The module &lt;a
href=&quot;https://metacpan.org/pod/Systemd::Daemon&quot;&gt;Systemd::Daemon&lt;/a&gt;
module gives you access to &lt;code&gt;sd_notify&lt;/code&gt; in Perl.&lt;/p&gt;

&lt;p&gt;A minimal Perl program that can be watchdog'ed looks like
this:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;synPreProc&quot;&gt;#!/usr/bin/env perl&lt;/span&gt;
&lt;span class=&quot;synStatement&quot;&gt;use &lt;/span&gt;&lt;span class=&quot;synConstant&quot;&gt;5.020&lt;/span&gt;;
&lt;span class=&quot;synStatement&quot;&gt;use warnings&lt;/span&gt;;
&lt;span class=&quot;synStatement&quot;&gt;use strict&lt;/span&gt;;
&lt;span class=&quot;synStatement&quot;&gt;use &lt;/span&gt;Time::HiRes &lt;span class=&quot;synConstant&quot;&gt;qw(usleep)&lt;/span&gt;;
&lt;span class=&quot;synStatement&quot;&gt;use &lt;/span&gt;Systemd::Daemon &lt;span class=&quot;synConstant&quot;&gt;qw( -hard notify )&lt;/span&gt;;

&lt;span class=&quot;synStatement&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;synIdentifier&quot;&gt;$sleep&lt;/span&gt; = (&lt;span class=&quot;synIdentifier&quot;&gt;$ENV{&lt;/span&gt;&lt;span class=&quot;synConstant&quot;&gt;WATCHDOG_USEC&lt;/span&gt;&lt;span class=&quot;synIdentifier&quot;&gt;}&lt;/span&gt; // &lt;span class=&quot;synConstant&quot;&gt;2_000_000&lt;/span&gt;) / &lt;span class=&quot;synConstant&quot;&gt;2&lt;/span&gt;;
&lt;span class=&quot;synIdentifier&quot;&gt;$|&lt;/span&gt; = &lt;span class=&quot;synConstant&quot;&gt;1&lt;/span&gt;;
notify( &lt;span class=&quot;synConstant&quot;&gt;READY&lt;/span&gt; =&amp;gt; &lt;span class=&quot;synConstant&quot;&gt;1&lt;/span&gt; );

&lt;span class=&quot;synStatement&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;synConstant&quot;&gt;1&lt;/span&gt;) {
    usleep &lt;span class=&quot;synIdentifier&quot;&gt;$sleep&lt;/span&gt;;
    &lt;span class=&quot;synStatement&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;synConstant&quot;&gt;&amp;quot;watchdog&amp;quot;&lt;/span&gt;;
    notify( &lt;span class=&quot;synConstant&quot;&gt;WATCHDOG&lt;/span&gt; =&amp;gt; &lt;span class=&quot;synConstant&quot;&gt;1&lt;/span&gt; );
}
&lt;/pre&gt;

&lt;p&gt;If you forget the &lt;code&gt;READY&lt;/code&gt; notification, a
&lt;code&gt;systemctl start $service&lt;/code&gt; hangs (until it runs
into a timeout), and &lt;code&gt;systemctl status $service&lt;/code&gt;
says &lt;code&gt;Active: activating (start) since ...&lt;/code&gt;. The
normal state is &lt;code&gt;Active: active (running)
since&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the service misses its heartbeat, it looks like this
in the log (&lt;code&gt;journalctl -u $service&lt;/code&gt;; timestamps
and hostname stripped):&lt;/p&gt;

&lt;pre&gt;
systemd[1]: testdaemon.service: Watchdog timeout (limit 10s)!
systemd[1]: testdaemon.service: Main process exited, code=dumped, status=6/ABRT
systemd[1]: testdaemon.service: Unit entered failed state.
systemd[1]: testdaemon.service: Failed with result 'core-dump'.
systemd[1]: testdaemon.service: Service hold-off time over, scheduling restart.
systemd[1]: Stopped Testdaemon.
systemd[1]: Starting Testdaemon...
systemd[1]: Started Testdaemon.
&lt;/pre&gt;

&lt;p&gt;And this is the corresponding unit file:&lt;/p&gt;

&lt;pre&gt;
[Unit]
Description=Testdaemon
After=syslog.target network.target

[Service]
Type=notify
NotifyAccess=main
Restart=always
WatchdogSec=10

User=moritz
Group=moritz
ExecStart=/home/moritz/testdaemon.pl

[Install]
WantedBy=multi-user.target
&lt;/pre&gt;

&lt;p&gt;Relevant here are &lt;code&gt;Type=notify&lt;/code&gt;, which enables the
watchdog, &lt;code&gt;Restart=always&lt;/code&gt; as the restart policy,
and &lt;code&gt;WatchdogSec=10&lt;/code&gt; for 10 second period after
which the service restarts if no &lt;code&gt;sd_notify&lt;/code&gt; of
type &lt;code&gt;WATCHDOG&lt;/code&gt; occurred.&lt;/p&gt;

&lt;p&gt;Systemd makes the &lt;code&gt;WatchdogSec&lt;/code&gt; setting
available as the environment variable
&lt;code&gt;WATCHDOG_USEC&lt;/code&gt;, converted to microseconds (so
multiplied by one million). If the server process aims to
report heartbeats twice as often as that wait period, small
timing errors should not lead to a missed heartbeat.&lt;/p&gt;

&lt;p&gt;In my case, the WATCHDOG notification happens in an
&lt;code&gt;AnyEvent-&amp;gt;timer&lt;/code&gt; callback, so if this doesn't
happen, either the event loop got stuck, or a blocking
operation prevents the event loop from running. The latter
should not happen (blocking operations are meant to run in
forked processes), so this adequately detects the error I
want to detect.&lt;/p&gt;

&lt;p&gt;For the little functionality that I use, Systemd::Daemon
is a pretty heavy dependency (using XS and quite a few build
dependencies). After looking a &lt;a
href=&quot;https://github.com/bb4242/sdnotify/blob/master/sdnotify/__init__.py&quot;&gt;reimplementation
of the notify() protocol in python&lt;/a&gt;, I wonder if talking
to the socket directly would have been less work than
packaging Systemd::Daemon.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;Systemd offers a heartbeat supervisor for processes that
manage it. It can automatically restart processes that fail
to check in regularly via calls to &lt;code&gt;sd_notify&lt;/code&gt;,
or doing the equivalent action on a socket. Perl's
Systemd::Daemon module gives you access to sd_notify in a
Perl server process.&lt;/p&gt;

  
</description>
  </item>
  <item>
 <title>Perl 6 Fundamentals Now Available for Purchase</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-018-perl6-fundamentals-available-for-purchase.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Fri, 21 Jul 2017 22:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-07-22 --&gt;
&lt;p&gt;After about nine months of work, my book
&lt;a href=&quot;https://www.apress.com/us/book/9781484228982&quot;&gt;Perl 6 Fundamentals&lt;/a&gt; is now available for purchase on &lt;a href=&quot;https://www.apress.com/us/book/9781484228982&quot;&gt;apress.com&lt;/a&gt; and &lt;a href=&quot;http://www.springer.com/us/book/9781484228982&quot;&gt;springer.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The ebook can be purchased right now, and comes in the epub and PDF formats (with watermarks, but DRM free). The print form can be pre-ordered from &lt;a href=&quot;https://www.amazon.com/dp/1484228987&quot;&gt;Amazon&lt;/a&gt;, and will become ready for shipping in about a week or two.&lt;/p&gt;

&lt;p&gt;I will make a copy of the ebook available for free for everybody who purchased an earlier version, &quot;Perl 6 by Example&quot;, from LeanPub.&lt;/p&gt;

&lt;p&gt;The book is aimed at people familiar with the basics of programming; prior
Perl 5 or Perl 6 knowledge is not required. It features a practical example in most chapters (no mammal hierarchies or &lt;code&gt;class Rectangle&lt;/code&gt; inheriting from &lt;code&gt;class Shape&lt;/code&gt;), ranging from simple input/output and text formatting to plotting with python's matplotlib libraries. Other examples include date and time conversion, a Unicode search tool and a directory size visualization.&lt;/p&gt;

&lt;p&gt;I use these examples to explain subset of Perl 6, with many pointers to more
documentation where relevant. Perl 6 topics include the basic lexicographic
structure, testing, input and output, multi dispatch, object orientation, regexes and grammars, usage of modules, functional programming and interaction
with python libraries through &lt;code&gt;Inline::Python&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let me finish with Larry Wall's description of this book, quoted from his foreword:&lt;/p&gt;

&lt;blockquote&gt;
It's not just a reference, since you can always find such
materials online.  Nor is it just a cookbook.  I like to think of it as an
extended invitation, from a well-liked and well-informed member of our circle,
to people like you who might want to join in on the fun.  Because joy is
what's fundamental to Perl.  The essence of Perl is an invitation to
love, and to be loved by, the Perl community.  It's an invitation to be a
participant of the gift economy, on both the receiving and the giving end.
&lt;/blockquote&gt;



</description>
  </item>
  <item>
 <title>The Loss of Name and Orientation</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-018-losing-named-and-orientation.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Mon, 10 Jul 2017 22:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-07-11 --&gt;

&lt;p&gt;The &lt;a href=&quot;https://perl6.party/post/The-Hot-New-Language-Named-Rakudo&quot;&gt;Perl 6 naming debate has started again&lt;/a&gt;. And I guess with good reason. Teaching people that Perl 6 is &lt;i&gt;a&lt;/i&gt; Perl, but not &lt;i&gt;the&lt;/i&gt; Perl requires too much effort. Two years ago, I didn't believe. Now you're reading a tired man's words.&lt;/p&gt;

&lt;p&gt;I'm glad that this time, we're not discussing giving up the &quot;Perl&quot; brand, which still has very positive connotations in my mind, and in many other minds as well.&lt;/p&gt;

&lt;p&gt;And yet, I can't bring myself to like &quot;Rakudo Perl 6&quot; as a name. There are two vary shallow reasons for that: Going from two syllables, &quot;Perl six&quot;, to five of them, seems a step in the wrong direction. And two, I remember the days when the name was pretty young, and people would misspell it all the time. That seems to have abated, though I don't know why.&lt;/p&gt;

&lt;p&gt;But there's also a deeper reason, probably sentimental old man's reason. I remember the days when Pugs was actively developed, and formed the center of a vibrant community. When kp6 and SMOP and all those weird projects were around. And then, just when it looked like there was only a single compiler was around, Stefan O'Rear conjured up niecza, almost single-handedly, and out of thin air. Within months, it was a viable Perl 6 compiler, that people on #perl6 readily recommended.&lt;/p&gt;

&lt;p&gt;All of this was born out of the vision that Perl 6 was a language with no single, preferred compiler. Changing the language name to include the compiler name means abandoning this vision. How can we claim to welcome alternative implementations when the commitment to one compiler is right in the language name?&lt;/p&gt;

&lt;p&gt;However I can't weigh this loss of vision against a potential gain in popularity. I can't decide if it's my long-term commitment to the name &quot;Perl 6&quot; that makes me resent the new name, or valid objections. The lack of vision mirrors my own state of mind pretty well.&lt;/p&gt;

&lt;p&gt;I don't know where this leaves us. I guess I must apologize for wasting your time by publishing this incoherent mess.&lt;/p&gt;


</description>
  </item>
  <item>
 <title>Living on the (b)leading edge</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-017-living-on-the-bleading-edge.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Sat, 24 Jun 2017 22:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-06-25 --&gt;

&lt;p&gt;Perl 6 is innovative in many ways, and sometimes we don't fully
appreciate all the implications, for good or for bad.&lt;/p&gt;

&lt;p&gt;There's one I stumbled upon recently: The use of fancy Unicode
symbols for built-in stuff. In this case: the `.gist` output of Match
objects. For example&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;synSpecial&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;synStatement&quot;&gt;token&lt;/span&gt; word {&lt;span class=&quot;synConstant&quot;&gt; &lt;/span&gt;&lt;span class=&quot;synSpecial&quot;&gt;\w+&lt;/span&gt;&lt;span class=&quot;synConstant&quot;&gt; &lt;/span&gt;}
&lt;span class=&quot;synIdentifier&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;synSpecial&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;synConstant&quot;&gt;abc=def&lt;/span&gt;&lt;span class=&quot;synSpecial&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;synStatement&quot;&gt;~~&lt;/span&gt; &lt;span class=&quot;synSpecial&quot;&gt;/&amp;lt;&lt;/span&gt;word&lt;span class=&quot;synSpecial&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;synConstant&quot;&gt; &lt;/span&gt;&lt;span class=&quot;synSpecial&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;synConstant&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;synSpecial&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;synConstant&quot;&gt; &lt;/span&gt;&lt;span class=&quot;synSpecial&quot;&gt;&amp;lt;&lt;/span&gt;word&lt;span class=&quot;synSpecial&quot;&gt;&amp;gt;/&lt;/span&gt;&lt;span class=&quot;synStatement&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;

produces this output:

&lt;pre&gt;
｢abc=def｣
 word =&amp;gt; ｢abc｣
 word =&amp;gt; ｢def｣
&lt;/pre&gt;

&lt;p&gt;And that's where the problems start. In my current &lt;a
href=&quot;https://leanpub.com/perl6regex&quot;&gt;quest to write a book on Perl 6
regexes&lt;/a&gt;, I noticed that the PDF that LeanPub generates from my
Markdown sources don't correctly display those pesky ｢｣ characters,
which are

&lt;pre&gt;
$ uni -c ｢｣
｢ - U+0FF62 - HALFWIDTH LEFT CORNER BRACKET
｣ - U+0FF63 - HALFWIDTH RIGHT CORNER BRACKET
&lt;/pre&gt;

&lt;p&gt;When I copied the text from the PDF and pasted into my editor, they
showed up correctly, which indicates that the characters are likely
missing from the monospace font.&lt;/p&gt;

&lt;p&gt;The toolchain allows control over the font used for displaying code,
so I tried all the monospace fonts that were available. I tried them in
alphabetical order. Among the earlier fonts I tried was Deja Vu Sans
Mono, which I use in my terminal, and which hasn't let me down yet. No
dice. I arrived at &lt;a
href&quot;https://www.google.com/get/noto/&quot;&gt;Noto&lt;/a&gt;, a font designed to
cover all Unicode codepoints. And it didn't work either. So it turns out
these two characters are part of some Noto Sans variants, but not of the
monospace font.&lt;/p&gt;

&lt;p&gt;My terminal, and even some font viewers, use some kind of fallback
where they use glyphs from other fonts to render missing characters. The
book generation toolchain does not.&lt;/p&gt;

&lt;p&gt;The Google Group for Leanpub was &lt;a
href=&quot;https://groups.google.com/forum/#!topic/leanpub/bqVazrui-O4&quot;&gt;somewhat
helpful:&lt;/a&gt; if I could recommend an Open Source mono space font that
fit my needs, they'd likely include it in their toolchain.&lt;/p&gt;

&lt;p&gt;So I searched and searched, learning more about fonts than I wanted
to know. My circle of geek friends came up with several suggestions, one
of them being &lt;a href=&quot;https://github.com/be5invis/Iosevka&quot;&gt;Iosevka&lt;/a&gt;,
which actually contains those characters. So now I wait for others to
step up, either for LeanPub to include that font, or for &lt;a
href=&quot;https://github.com/googlei18n/noto-fonts/issues/939&quot;&gt;the Noto
maintainers to create a monospace variant of those characters&lt;/a&gt; (and
then LeanPub updating their version of the font).&lt;/p&gt;

&lt;p&gt;And all of that because Perl 6 was being innovative, and used two
otherwise little-used characters as delimiters, in an attempt to avoid
collisions between delimiters and content.&lt;/p&gt;

&lt;p&gt;(In the mean time I've replaced the two offending characters with
ones that look similar. It means the example output is technically
incorrect, but at least it's readable).&lt;/p&gt;


</description>
  </item>
  <item>
 <title>Perl 6 Books Landscape in June 2017</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-016-books-landscape.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Wed, 07 Jun 2017 22:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-06-08 --&gt;

&lt;p&gt;There are lots of news around Perl 6 books to share these days. If you follow the community very closely, you might be aware of most of it. If not, read on :-).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://shop.oreilly.com/product/0636920065883.do&quot;&gt;Think Perl 6&lt;/a&gt; is now available for purchase, and also for download as a &lt;a href=&quot;http://greenteapress.com/wp/think-perl-6/&quot;&gt;free ebook&lt;/a&gt;. Heck, it's even &lt;a href=&quot;https://github.com/LaurentRosenfeld/thinkperl6/&quot;&gt;Open Source, with the LaTeX sources on GitHub!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://deeptext.media/perl6-at-a-glance&quot;&gt;Perl 6 at a Glance&lt;/a&gt;, previously only available in print form, is now available as an ebook. Save paper and shipping costs!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My own book, &lt;a href=&quot;https://www.apress.com/us/book/9781484228982&quot;&gt;Perl 6 Fundamentals&lt;/a&gt;, is now in the &quot;production&quot; phase: copyediting, indexing, layout. And just before the manuscript submission deadline, Larry Wall has contributed a foreword. How awesome is that?&lt;/p&gt;

&lt;p&gt;I've revamped &lt;a href=&quot;https://perl6book.com/&quot;&gt;perl6book.com&lt;/a&gt; to provide a short overview of the current and future Perl 6 books. As a small gimmick, it contains a flow chart explaining which book to chose. And I even got input from two other Perl 6 book authors (Laurent Rosenfeld of &quot;Think Perl 6&quot;, Andrew Shitov of &quot;Perl 6 at a Glance&quot;, &quot;Migrating to Perl 6&quot;.&lt;/p&gt;

&lt;p&gt;From a &lt;a href=&quot;https://github.com/moritz/perl6book-web/pull/2/files&quot;&gt;pull request to perl6book.com&lt;/a&gt;, it looks like Andrew Shitov is working on two more Perl 6 books. Keep 'em coming!&lt;/p&gt;

&lt;p&gt;Last but not least, Gabor Szabo has started a &lt;a href=&quot;https://www.indiegogo.com/projects/book-web-application-development-in-perl-6-website--2/x/16699245#/&quot;&gt;crowd funding campaign for a Perl 6 book on web app development&lt;/a&gt;. There are still a few day left, so you can help it succeed!&lt;/p&gt;

&lt;p&gt;And as always, if you want to keep informed about Perl 6 books, you can sign up at &lt;a href=&quot;https://perl6book.com/&quot;&gt;perl6book.com for my Perl 6 books mailing list&lt;/a&gt; (low volume, typically less than one email per month).&lt;/p&gt; 



</description>
  </item>
  <item>
 <title>Perl 6 By Example: Now &quot;Perl 6 Fundamentals&quot;</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-015-book-update.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Sun, 30 Apr 2017 22:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-05-01 --&gt;
&lt;p style=&quot;width: 190; float:right; padding: 10px&quot;&gt;&lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;&lt;img
src=&quot;https://perlgeek.de/images/blog/p6/book-cover-thumbnail.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog post is part of my &lt;a
href=&quot;https://perlgeek.de/blog-en/perl-6/2016-book.html&quot;&gt;ongoing project&lt;/a&gt;
to write a &lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;book about Perl 6&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're interested, either in this book project or any other Perl 6 book news, please sign up for the mailing list at the bottom of
the article, or &lt;a href=&quot;https://perl6book.com/#signup&quot;&gt;here&lt;/a&gt;. It will be
low volume (less than an email per month, on average).&lt;/p&gt;

&lt;hr style=&quot;clear: right&quot; /&gt;


&lt;p&gt;After some silence during the past few weeks, I can finally share
some exciting news about the book project. &lt;a href=&quot;https://www.apress.com/&quot;&gt;Apress&lt;/a&gt;
has agreed to publish the book, both as print and electronic book.&lt;/p&gt;

&lt;p&gt;The title is &lt;a href=&quot;http://www.apress.com/gp/book/9781484228982&quot;&gt;&lt;em&gt;Perl 6
Fundamentals&lt;/em&gt;&lt;/a&gt;, with &lt;em&gt;A Primer with Examples, 
Projects, and Case Studies&lt;/em&gt; as subtitle. The editorial process is happening
right now. I've received some great feedback on my initial manuscript, so there's
a lot to do for me.&lt;/p&gt;

&lt;p&gt;Stay tuned for more updates!&lt;/p&gt;

&lt;div id=&quot;mc_embed_signup&quot;&gt;
&lt;form action=&quot;//perlgeek.us12.list-manage.com/subscribe/post?u=ea4954d15b6283987b9d1b161&amp;amp;id=207c668582&quot; method=&quot;post&quot; id=&quot;mc-embedded-subscribe-form&quot; name=&quot;mc-embedded-subscribe-form&quot; class=&quot;validate&quot; target=&quot;_blank&quot; novalidate&gt;
    &lt;div id=&quot;mc_embed_signup_scroll&quot;&gt;
	&lt;h2&gt;Subscribe to the Perl 6 book mailing list&lt;/h2&gt;
&lt;div class=&quot;indicates-required&quot;&gt;&lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt; indicates required&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-EMAIL&quot;&gt;Email Address  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;email&quot; value=&quot;&quot; name=&quot;EMAIL&quot; class=&quot;required email&quot; id=&quot;mce-EMAIL&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-FNAME&quot;&gt;First Name  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;text&quot; value=&quot;&quot; name=&quot;FNAME&quot; class=&quot;required&quot; id=&quot;mce-FNAME&quot;&gt;
&lt;/div&gt;
	&lt;div id=&quot;mce-responses&quot; class=&quot;clear&quot;&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-error-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-success-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
	&lt;/div&gt;    &lt;!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups--&gt;
    &lt;div style=&quot;position: absolute; left: -5000px;&quot; aria-hidden=&quot;true&quot;&gt;&lt;input type=&quot;text&quot; name=&quot;b_ea4954d15b6283987b9d1b161_207c668582&quot; tabindex=&quot;-1&quot; value=&quot;&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;clear&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;Subscribe&quot; name=&quot;subscribe&quot; id=&quot;mc-embedded-subscribe&quot; class=&quot;button&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'&gt;&lt;/script&gt;&lt;script type='text/javascript'&gt;(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';fnames[1]='FNAME';ftypes[1]='text';}(jQuery));var $mcj = jQuery.noConflict(true);&lt;/script&gt;
&lt;!--End mc_embed_signup--&gt;



</description>
  </item>
  <item>
 <title>Perl 6 By Example: Idiomatic Use of Inline::Python</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-014-idiomatic-inline-python.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Sat, 01 Apr 2017 22:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-04-02 --&gt;
&lt;p style=&quot;width: 190; float:right; padding: 10px&quot;&gt;&lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;&lt;img
src=&quot;https://perlgeek.de/images/blog/p6/book-cover-thumbnail.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog post is part of my &lt;a
href=&quot;https://perlgeek.de/blog-en/perl-6/2016-book.html&quot;&gt;ongoing project&lt;/a&gt;
to write a &lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;book about Perl 6&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're interested, either in this book project or any other Perl 6 book news, please sign up for the mailing list at the bottom of
the article, or &lt;a href=&quot;https://perl6book.com/#signup&quot;&gt;here&lt;/a&gt;. It will be
low volume (less than an email per month, on average).&lt;/p&gt;

&lt;hr style=&quot;clear: right&quot; /&gt;


&lt;p&gt;In the two
&lt;a href=&quot;https://perlgeek.de/blog-en/perl-6/2017-012-inline-python.html&quot;&gt;previous&lt;/a&gt;
&lt;a href=&quot;https://perlgeek.de/blog-en/perl-6/2017-013-inline-python-stacked.html&quot;&gt;installments&lt;/a&gt;,
we've seen Python libraries being used in Perl 6 code through the
&lt;a href=&quot;https://github.com/niner/Inline-Python&quot;&gt;Inline::Python&lt;/a&gt; module. Here
we will explore some options to make the Perl 6 code more idiomatic and
closer to the documentation of the Python modules.&lt;/p&gt;

&lt;h2&gt;Types of Python APIs&lt;/h2&gt;

&lt;p&gt;Python is an object-oriented language, so many APIs involve method
calls, which &lt;code&gt;Inline::Python&lt;/code&gt; helpfully automatically translates for us.&lt;/p&gt;

&lt;p&gt;But the objects must come from somewhere and typically this is by
calling a function that returns an object, or by instantiating a class.
In Python, those two are really the same under the hood, since
instantiating a class is the same as calling the class as if it were a
function.&lt;/p&gt;

&lt;p&gt;An example of this (in Python) would be&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;from matplotlib.pyplot import subplots
result = subplots()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But the matplotlib documentation tends to use another, equivalent
syntax:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import matplotlib.pyplot as plt
result = plt.subplots()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This uses the &lt;code&gt;subplots&lt;/code&gt; symbol (class or function) as a method on the
module &lt;code&gt;matplotlib.pyplot&lt;/code&gt;, which the import statement aliases to &lt;code&gt;plt&lt;/code&gt;.
This is a more object-oriented syntax for the same API.&lt;/p&gt;

&lt;h2&gt;Mapping the Function API&lt;/h2&gt;

&lt;p&gt;The previous code examples used this Perl 6 code to call the &lt;code&gt;subplots&lt;/code&gt;
symbol:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $py = Inline::Python.new;
$py.run('import matplotlib.pyplot');
sub plot(Str $name, |c) {
    $py.call('matplotlib.pyplot', $name, |c);
}

my ($figure, $subplots) = plot('subplots');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we want to call &lt;code&gt;subplots()&lt;/code&gt; instead of &lt;code&gt;plot('subplots')&lt;/code&gt;, and
&lt;code&gt;bar(args)&lt;/code&gt; instead of `plot('bar', args), we can use a function to
generate wrapper functions:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $py = Inline::Python.new;

sub gen(Str $namespace, *@names) {
    $py.run(&quot;import $namespace&quot;);

    return @names.map: -&amp;gt; $name {
        sub (|args) {
            $py.call($namespace, $name, |args);
        }
    }
}

my (&amp;amp;subplots, &amp;amp;bar, &amp;amp;legend, &amp;amp;title, &amp;amp;show)
    = gen('matplotlib.pyplot', &amp;lt;subplots bar legend title show&amp;gt;);

my ($figure, $subplots) = subplots();

# more code here

legend($@plots, $@top-authors);
title('Contributions per day');
show();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This makes the functions' usage quite nice, but comes at the cost
of duplicating their names. One can view this as a
feature, because it allows the creation of different aliases, or as a
source for bugs when the order is messed up, or a name misspelled.&lt;/p&gt;

&lt;p&gt;How could we avoid the duplication should we choose to create wrapper
functions?&lt;/p&gt;

&lt;p&gt;This is where Perl 6's flexibility and introspection abilities pay off.
There are two key components that allow a nicer solution: the fact that
declarations are expressions and that you can introspect variables for
their names.&lt;/p&gt;

&lt;p&gt;The first part means you can write &lt;code&gt;mysub my ($a, $b)&lt;/code&gt;, which
declares the variables &lt;code&gt;$a&lt;/code&gt; and &lt;code&gt;$b&lt;/code&gt;, and calls a function with those
variables as arguments. The second part means that &lt;code&gt;$a.VAR.name&lt;/code&gt; returns
a string &lt;code&gt;'$a'&lt;/code&gt;, the name of the variable.&lt;/p&gt;

&lt;p&gt;Let's combine this to create a wrapper that initializes subroutines for
us:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub pysub(Str $namespace, |args) {
    $py.run(&quot;import $namespace&quot;);

    for args[0] &amp;lt;-&amp;gt; $sub {
        my $name = $sub.VAR.name.substr(1);
        $sub = sub (|args) {
            $py.call($namespace, $name, |args);
        }
    }
}

pysub 'matplotlib.pyplot',
    my (&amp;amp;subplots, &amp;amp;bar, &amp;amp;legend, &amp;amp;title, &amp;amp;show);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This avoids duplicating the name, but forces us to use some lower-level
Perl 6 features in sub &lt;code&gt;pysub&lt;/code&gt;. Using ordinary variables means that accessing their
&lt;code&gt;.VAR.name&lt;/code&gt; results in the name of the variable, not the name of the
variable that's used on the caller side. So we can't use slurpy
arguments as in&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub pysub(Str $namespace, *@subs)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Instead we must use
&lt;code&gt;|args&lt;/code&gt; to obtain the rest of the arguments in a
&lt;a href=&quot;https://docs.perl6.org/type/Capture.html&quot;&gt;Capture&lt;/a&gt;. This doesn't
flatten the list of variables passed to the function, so when we iterate
over them, we must do so by accessing &lt;code&gt;args[0]&lt;/code&gt;. By default, loop
variables are read-only, which we can avoid by using &lt;code&gt;&amp;lt;-&amp;gt;&lt;/code&gt; instead of
&lt;code&gt;-&amp;gt;&lt;/code&gt; to introduce the signature. Fortunately, that also preserves the
name of the caller side variable.&lt;/p&gt;

&lt;h2&gt;An Object-Oriented Interface&lt;/h2&gt;

&lt;p&gt;Instead of exposing the functions, we can also create types that emulate
the method calls on Python modules. For that we can implement a class with a
method &lt;code&gt;FALLBACK&lt;/code&gt;, which Perl 6 calls for us when calling a method that is not
implemented in the class:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class PyPlot is Mu {
    has $.py;
    submethod TWEAK {
        $!py.run('import matplotlib.pyplot');
    }
    method FALLBACK($name, |args) {
        $!py.call('matplotlib.pyplot', $name, |args);
    }
}

my $pyplot = PyPlot.new(:$py);
my ($figure, $subplots) = $pyplot.subplots;
# plotting code goes here
$pyplot.legend($@plots, $@top-authors);

$pyplot.title('Contributions per day');
$pyplot.show;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Class &lt;code&gt;PyPlot&lt;/code&gt; inherits directly from &lt;code&gt;Mu&lt;/code&gt;, the root of the Perl 6 type
hierarchy, instead of &lt;code&gt;Any&lt;/code&gt;, the default parent class (which in turn inherits
from &lt;code&gt;Mu&lt;/code&gt;). &lt;code&gt;Any&lt;/code&gt; introduces a large number of methods that Perl 6 objects
get by default and since &lt;code&gt;FALLBACK&lt;/code&gt; is only invoked when a method is not
present, this is something to avoid.&lt;/p&gt;

&lt;p&gt;The method &lt;code&gt;TWEAK&lt;/code&gt; is another method that
Perl 6 calls automatically for us, after the object has been fully
instantiated. All-caps method names are reserved for such special purposes.
It is marked as a &lt;code&gt;submethod&lt;/code&gt;, which means it is not inherited into subclasses.
Since &lt;code&gt;TWEAK&lt;/code&gt; is called at the level of each class, if it were a regular
method, a subclass would call it twice implicitly. Note that &lt;code&gt;TWEAK&lt;/code&gt; is only
supported in Rakudo version 2016.11 and later.&lt;/p&gt;

&lt;p&gt;There's nothing specific to the Python package &lt;code&gt;matplotlib.pyplot&lt;/code&gt; in class
&lt;code&gt;PyPlot&lt;/code&gt;, except the namespace name. We could easily generalize it to any
namespace:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class PythonModule is Mu {
    has $.py;
    has $.namespace;
    submethod TWEAK {
        $!py.run(&quot;import $!namespace&quot;);
    }
    method FALLBACK($name, |args) {
        $!py.call($!namespace, $name, |args);
    }
}

my $pyplot = PythonModule.new(:$py, :namespace&amp;lt;matplotlib.pyplot&amp;gt;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is one Perl 6 type that can represent any Python module. If instead we
want a separate Perl 6 type for each Python module, we could use roles, which
are optionally parameterized:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;role PythonModule[Str $namespace] is Mu {
    has $.py;
    submethod TWEAK {
        $!py.run(&quot;import $namespace&quot;);
    }
    method FALLBACK($name, |args) {
        $!py.call($namespace, $name, |args);
    }
}

my $pyplot = PythonModule['matplotlib.pyplot'].new(:$py);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using this approach, we can create type constraints for Python modules in
Perl 6 space:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub plot-histogram(PythonModule['matplotlib.pyplot'], @data) {
    # implementation here
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Passing in any other wrapped Python module than &lt;code&gt;matplotlib.pyplot&lt;/code&gt; results
in a type error.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;Perl 6 offers enough flexibility to create function and method call APIs
around Python modules. With a bit of meta programming, we can emulate the
typical Python APIs close enough that translating from the Python
documentation to Perl 6 code becomes easy.&lt;/p&gt;

&lt;div id=&quot;mc_embed_signup&quot;&gt;
&lt;form action=&quot;//perlgeek.us12.list-manage.com/subscribe/post?u=ea4954d15b6283987b9d1b161&amp;amp;id=207c668582&quot; method=&quot;post&quot; id=&quot;mc-embedded-subscribe-form&quot; name=&quot;mc-embedded-subscribe-form&quot; class=&quot;validate&quot; target=&quot;_blank&quot; novalidate&gt;
    &lt;div id=&quot;mc_embed_signup_scroll&quot;&gt;
	&lt;h2&gt;Subscribe to the Perl 6 book mailing list&lt;/h2&gt;
&lt;div class=&quot;indicates-required&quot;&gt;&lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt; indicates required&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-EMAIL&quot;&gt;Email Address  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;email&quot; value=&quot;&quot; name=&quot;EMAIL&quot; class=&quot;required email&quot; id=&quot;mce-EMAIL&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-FNAME&quot;&gt;First Name  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;text&quot; value=&quot;&quot; name=&quot;FNAME&quot; class=&quot;required&quot; id=&quot;mce-FNAME&quot;&gt;
&lt;/div&gt;
	&lt;div id=&quot;mce-responses&quot; class=&quot;clear&quot;&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-error-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-success-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
	&lt;/div&gt;    &lt;!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups--&gt;
    &lt;div style=&quot;position: absolute; left: -5000px;&quot; aria-hidden=&quot;true&quot;&gt;&lt;input type=&quot;text&quot; name=&quot;b_ea4954d15b6283987b9d1b161_207c668582&quot; tabindex=&quot;-1&quot; value=&quot;&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;clear&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;Subscribe&quot; name=&quot;subscribe&quot; id=&quot;mc-embedded-subscribe&quot; class=&quot;button&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'&gt;&lt;/script&gt;&lt;script type='text/javascript'&gt;(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';fnames[1]='FNAME';ftypes[1]='text';}(jQuery));var $mcj = jQuery.noConflict(true);&lt;/script&gt;
&lt;!--End mc_embed_signup--&gt;



</description>
  </item>
  <item>
 <title>Perl 6 By Example: Stacked Plots with Matplotlib</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-013-inline-python-stacked.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Sat, 25 Mar 2017 23:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-03-26 --&gt;
&lt;p style=&quot;width: 190; float:right; padding: 10px&quot;&gt;&lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;&lt;img
src=&quot;https://perlgeek.de/images/blog/p6/book-cover-thumbnail.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog post is part of my &lt;a
href=&quot;https://perlgeek.de/blog-en/perl-6/2016-book.html&quot;&gt;ongoing project&lt;/a&gt;
to write a &lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;book about Perl 6&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're interested, either in this book project or any other Perl 6 book news, please sign up for the mailing list at the bottom of
the article, or &lt;a href=&quot;https://perl6book.com/#signup&quot;&gt;here&lt;/a&gt;. It will be
low volume (less than an email per month, on average).&lt;/p&gt;

&lt;hr style=&quot;clear: right&quot; /&gt;


&lt;p&gt;In a previous episode, we've &lt;a href=&quot;https://perlgeek.de/blog-en/perl-6/2017-012-inline-python.html&quot;&gt;explored plotting git statistics in Perl 6 using
matplotlib&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since I wasn't quite happy with the result, I want to explore using stacked
plots for presenting the same information. In a regular plot, the y
coordiante of each plotted value is proportional to its value. In a
stacked plot, it is the distance to the previous value that is
proportional to its value. This is nice for values that add up to a
total that is also interesting.&lt;/p&gt;

&lt;p&gt;Matplotlib offers a &lt;a href=&quot;http://matplotlib.org/devdocs/api/_as_gen/matplotlib.axes.Axes.stackplot.html&quot;&gt;method called
&lt;code&gt;stackplot&lt;/code&gt;&lt;/a&gt;
for that. Contrary to multiple &lt;code&gt;plot&lt;/code&gt; calls on subplot object, it
requires a shared x axis for all data series. So we must construct
one array for each author of git commits, where dates with no value come
out as zero.&lt;/p&gt;

&lt;p&gt;As a reminder, this is what the logic for extracting the stats looked
like in the first place:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $proc = run :out, &amp;lt;git log --date=short --pretty=format:%ad!%an&amp;gt;;
my (%total, %by-author, %dates);
for $proc.out.lines -&amp;gt; $line {
    my ( $date, $author ) = $line.split: '!', 2;
    %total{$author}++;
    %by-author{$author}{$date}++;
    %dates{$date}++;
}
my @top-authors = %total.sort(-*.value).head(5)&amp;gt;&amp;gt;.key;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And some infrastructure for plotting with matplotlib:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $py = Inline::Python.new;
$py.run('import datetime');
$py.run('import matplotlib.pyplot');
sub plot(Str $name, |c) {
    $py.call('matplotlib.pyplot', $name, |c);
}
sub pydate(Str $d) {
    $py.call('datetime', 'date', $d.split('-').map(*.Int));
}

my ($figure, $subplots) = plot('subplots');
$figure.autofmt_xdate();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now we have to construct an array of arrays, where each inner array
has the values for one author:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @dates = %dates.keys.sort;
my @stack = $[] xx @top-authors;

for @dates -&amp;gt; $d {
    for @top-authors.kv -&amp;gt; $idx, $author {
        @stack[$idx].push: %by-author{$author}{$d} // 0;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now plotting becomes a simple matter of a method call, followed by the
usual commands adding a title and showing the plot:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$subplots.stackplot($[@dates.map(&amp;amp;pydate)], @stack);
plot('title', 'Contributions per day');
plot('show');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The result (again run on the zef source repository) is this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://perlgeek.de/images/blog/perl-6/zef-contributors-stacked-1.png&quot; alt=&quot;Stacked plot of zef contributions over time&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Comparing this to the previous visualization reveals a discrepancy:
There were no commits in 2014, and yet the stacked plot makes it appear
this way. In fact, the previous plots would have shown the same
&quot;alternative facts&quot; if we had chosen lines instead of points. It comes
from matplotlib (like nearly all plotting libraries) interpolates
linearly between data points. But in our case, a date with no data
points means zero commits happened on that date.&lt;/p&gt;

&lt;p&gt;To communicate this to matplotlib, we must explicitly insert zero values
for missing dates. This can be achieved by replacing&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @dates = %dates.keys.sort;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;with the line&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @dates = %dates.keys.minmax;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;a href=&quot;https://docs.perl6.org/routine/minmax#class_Any&quot;&gt;&lt;code&gt;minmax&lt;/code&gt; method&lt;/a&gt;
finds the minimal and maximal values, and returns them in a
&lt;a href=&quot;https://docs.perl6.org/type/Range&quot;&gt;Range&lt;/a&gt;. Assigning the range to an
array turns it into an array of all values between the minimal and the
maximal value. The logic for assembling the &lt;code&gt;@stack&lt;/code&gt; variable already
maps missing values to zero.&lt;/p&gt;

&lt;p&gt;The result looks a bit better, but still far from perfect:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://perlgeek.de/images/blog/perl-6/zef-contributors-stacked-2.png&quot; alt=&quot;Stacked plot of zef contributions over time, with missing dates mapped to zero&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Thinking more about the problem, contributions from separate days should
not be joined together, because it produces misleading results.
Matplotlib doesn't support adding a legend automatically to stacked
plots, so this seems to be to be a dead end.&lt;/p&gt;

&lt;p&gt;Since a dot plot didn't work very well, let's try a different kind of
plot that represents each data point separately: a bar chart, or more
specifically, a stacked bar chart. Matplotlib offers the &lt;code&gt;bar&lt;/code&gt; plotting
method, and a named parameter &lt;code&gt;bottom&lt;/code&gt; can be used to generate the
stacking:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @dates = %dates.keys.sort;
my @stack = $[] xx @top-authors;
my @bottom = $[] xx @top-authors;

for @dates -&amp;gt; $d {
    my $bottom = 0;
    for @top-authors.kv -&amp;gt; $idx, $author {
        @bottom[$idx].push: $bottom;
        my $value = %by-author{$author}{$d} // 0;
        @stack[$idx].push: $value;
        $bottom += $value;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need to supply color names ourselves, and set the edge color of the
bars to the same color, otherwise the black edge color dominates the
result:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $width = 1.0;
my @colors = &amp;lt;red green blue yellow black&amp;gt;;
my @plots;

for @top-authors.kv -&amp;gt; $idx, $author {
    @plots.push: plot(
        'bar',
        $[@dates.map(&amp;amp;pydate)],
        @stack[$idx],
        $width,
        bottom =&amp;gt; @bottom[$idx],
        color =&amp;gt; @colors[$idx],
        edgecolor =&amp;gt; @colors[$idx],
    );
}
plot('legend', $@plots, $@top-authors);

plot('title', 'Contributions per day');
plot('show');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This produces the first plot that's actually informative and not
misleading (provided you're not color blind):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://perlgeek.de/images/blog/perl-6/zef-contributors-bars.png&quot; alt=&quot;Stacked bar plot of zef contributions over time&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you want to improve the result further, you could experiment with
limiting the number of bars by lumping together contributions by week or
month (or maybe &lt;code&gt;$n&lt;/code&gt;-day period).&lt;/p&gt;

&lt;p&gt;Next, we'll investigate ways to make the matplotlib API more idiomatic
to use from Perl 6 code.&lt;/p&gt;

&lt;div id=&quot;mc_embed_signup&quot;&gt;
&lt;form action=&quot;//perlgeek.us12.list-manage.com/subscribe/post?u=ea4954d15b6283987b9d1b161&amp;amp;id=207c668582&quot; method=&quot;post&quot; id=&quot;mc-embedded-subscribe-form&quot; name=&quot;mc-embedded-subscribe-form&quot; class=&quot;validate&quot; target=&quot;_blank&quot; novalidate&gt;
    &lt;div id=&quot;mc_embed_signup_scroll&quot;&gt;
	&lt;h2&gt;Subscribe to the Perl 6 book mailing list&lt;/h2&gt;
&lt;div class=&quot;indicates-required&quot;&gt;&lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt; indicates required&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-EMAIL&quot;&gt;Email Address  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;email&quot; value=&quot;&quot; name=&quot;EMAIL&quot; class=&quot;required email&quot; id=&quot;mce-EMAIL&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-FNAME&quot;&gt;First Name  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;text&quot; value=&quot;&quot; name=&quot;FNAME&quot; class=&quot;required&quot; id=&quot;mce-FNAME&quot;&gt;
&lt;/div&gt;
	&lt;div id=&quot;mce-responses&quot; class=&quot;clear&quot;&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-error-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-success-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
	&lt;/div&gt;    &lt;!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups--&gt;
    &lt;div style=&quot;position: absolute; left: -5000px;&quot; aria-hidden=&quot;true&quot;&gt;&lt;input type=&quot;text&quot; name=&quot;b_ea4954d15b6283987b9d1b161_207c668582&quot; tabindex=&quot;-1&quot; value=&quot;&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;clear&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;Subscribe&quot; name=&quot;subscribe&quot; id=&quot;mc-embedded-subscribe&quot; class=&quot;button&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'&gt;&lt;/script&gt;&lt;script type='text/javascript'&gt;(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';fnames[1]='FNAME';ftypes[1]='text';}(jQuery));var $mcj = jQuery.noConflict(true);&lt;/script&gt;
&lt;!--End mc_embed_signup--&gt;



</description>
  </item>
  <item>
 <title>Perl 6 By Example: Plotting using Matplotlib and Inline::Python</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-012-inline-python.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Sat, 18 Mar 2017 23:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-03-19 --&gt;
&lt;p style=&quot;width: 190; float:right; padding: 10px&quot;&gt;&lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;&lt;img
src=&quot;https://perlgeek.de/images/blog/p6/book-cover-thumbnail.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog post is part of my &lt;a
href=&quot;https://perlgeek.de/blog-en/perl-6/2016-book.html&quot;&gt;ongoing project&lt;/a&gt;
to write a &lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;book about Perl 6&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're interested, either in this book project or any other Perl 6 book news, please sign up for the mailing list at the bottom of
the article, or &lt;a href=&quot;https://perl6book.com/#signup&quot;&gt;here&lt;/a&gt;. It will be
low volume (less than an email per month, on average).&lt;/p&gt;

&lt;hr style=&quot;clear: right&quot; /&gt;


&lt;p&gt;Occasionally I come across git repositories, and want to know how active
they are, and who the main developers are.&lt;/p&gt;

&lt;p&gt;Let's develop a script that plots the commit history, and explore how to
use Python modules in Perl 6.&lt;/p&gt;

&lt;h2&gt;Extracting the Stats&lt;/h2&gt;

&lt;p&gt;We want to plot the number of commits by author and date.
Git makes it easy for us to get to this information by giving some options
to &lt;code&gt;git log&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $proc = run :out, &amp;lt;git log --date=short --pretty=format:%ad!%an&amp;gt;;
my (%total, %by-author, %dates);
for $proc.out.lines -&amp;gt; $line {
    my ( $date, $author ) = $line.split: '!', 2;
    %total{$author}++;
    %by-author{$author}{$date}++;
    %dates{$date}++;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;run&lt;/code&gt; executes an external command, and &lt;code&gt;:out&lt;/code&gt; tells it to capture the
command's output, and makes it available as &lt;code&gt;$proc.out&lt;/code&gt;. The command is
a list, with the first element being the actual executable, and the rest of
the elements are command line arguments to this executable.&lt;/p&gt;

&lt;p&gt;Here &lt;code&gt;git log&lt;/code&gt; gets the options &lt;code&gt;--date short --pretty=format:%ad!%an&lt;/code&gt;, which
instructs it to print produce lines like &lt;code&gt;2017-03-01!John Doe&lt;/code&gt;. This line
can be parsed with a simple call to &lt;code&gt;$line.split: '!', 2&lt;/code&gt;, which splits
on the &lt;code&gt;!&lt;/code&gt;, and limits the result to two elements. Assigning it to a
two-element list &lt;code&gt;( $date, $author )&lt;/code&gt; unpacks it. We then use hashes to
count commits by author (in &lt;code&gt;%total&lt;/code&gt;), by author and date (&lt;code&gt;%by-author&lt;/code&gt;)
and finally by date. In the second case, &lt;code&gt;%by-author{$author}&lt;/code&gt; isn't
even a hash yet, and we can still hash-index it. This is due to a feature
called &lt;em&gt;autovivification&lt;/em&gt;, which automatically creates (&quot;vivifies&quot;) objects
where we need them. The use of &lt;code&gt;++&lt;/code&gt; creates integers, &lt;code&gt;{...}&lt;/code&gt; indexing creates
hashes, &lt;code&gt;[...]&lt;/code&gt; indexing and &lt;code&gt;.push&lt;/code&gt; creates arrays, and so on.&lt;/p&gt;

&lt;p&gt;To get from these hashes to the top contributors by commit count, we can
sort &lt;code&gt;%total&lt;/code&gt; by value. Since this sorts in ascending order, sorting
by the negative value gives the list in descending order. The list contains
&lt;a href=&quot;https://docs.perl6.org/types/Pair&quot;&gt;Pair&lt;/a&gt; objects, and we only want the
first five of these, and only their keys:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @top-authors = %total.sort(-*.value).head(5).map(*.key);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For each author, we can extract the dates of their activity and their
commit counts like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @dates  = %by-author{$author}.keys.sort;
my @counts = %by-author{$author}{@dates};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The last line uses &lt;em&gt;slicing&lt;/em&gt;, that is, indexing an array with list to return a
list elements.&lt;/p&gt;

&lt;h2&gt;Plotting with Python&lt;/h2&gt;

&lt;p&gt;Matplotlib is a very versatile library for all sorts of plotting and
visualization. It's written in Python and for Python programs, but that
won't stop us from using it in a Perl 6 program.&lt;/p&gt;

&lt;p&gt;But first, let's take a look at a basic plotting example that uses dates
on the &lt;code&gt;x&lt;/code&gt; axis:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import datetime
import matplotlib.pyplot as plt

fig, subplots = plt.subplots()
subplots.plot(
    [datetime.date(2017, 1, 5), datetime.date(2017, 3, 5), datetime.date(2017, 5, 5)],
    [ 42, 23, 42 ],
    label='An example',
)
subplots.legend(loc='upper center', shadow=True)
fig.autofmt_xdate()
plt.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To make this run, you have to install python 2.7 and matplotlib. You can do
this on Debian-based Linux systems with &lt;code&gt;apt-get install -y python-matplotlib&lt;/code&gt;.
The package name is the same on RPM-based distributions such as CentOS or SUSE
Linux. MacOS users are advised to install a python 2.7 through homebrew and
macports, and then use &lt;code&gt;pip2 install matplotlib&lt;/code&gt; or &lt;code&gt;pip2.7 install
matplotlib&lt;/code&gt; to get the library. Windows installation is probably easiest
through the &lt;a href=&quot;https://conda.io/docs/&quot;&gt;conda&lt;/a&gt; package manager, which offers
pre-built binaries of both python and matplotlib.&lt;/p&gt;

&lt;p&gt;When you run this scripts with &lt;code&gt;python2.7 dates.py&lt;/code&gt;, it opens a GUI window, showing
the plot and some controls, which allow you to zoom, scroll, and write the
plot graphic to a file:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://perlgeek.de/images/blog/perl-6/matplotlib-window.png&quot; alt=&quot;Basic matplotlib plotting window&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;Bridging the Gap&lt;/h2&gt;

&lt;p&gt;The Rakudo Perl 6 compiler comes with a handy &lt;a href=&quot;https://docs.perl6.org/language/nativecall&quot;&gt;library for calling foreign
functions&lt;/a&gt;, which allows you to
call functions written in C, or anything with a compatible binary interface.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/niner/Inline-Python&quot;&gt;Inline::Python&lt;/a&gt; library uses
the native call functionality to talk to python's C API, and offers
interoperability between Perl 6 and Python code. At the time of writing, this
interoperability is still fragile in places, but can be worth using for
some of the great libraries that Python has to offer.&lt;/p&gt;

&lt;p&gt;To install &lt;code&gt;Inline::Python&lt;/code&gt;, you must have a C compiler available, and then
run&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ zef install Inline::Python
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(or the same with &lt;code&gt;panda&lt;/code&gt; instead of &lt;code&gt;zef&lt;/code&gt;, if that's your module installer).&lt;/p&gt;

&lt;p&gt;Now you can start to run Python 2 code in your Perl 6 programs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;use Inline::Python;

my $py = Inline::Python.new;
$py.run: 'print(&quot;Hello, Pyerl 6&quot;)';
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Besides the &lt;code&gt;run&lt;/code&gt; method, which takes a string of Python code and execute it,
you can also use &lt;code&gt;call&lt;/code&gt; to call Python routines by specifying the namespace,
the routine to call, and a list of arguments:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;use Inline::Python;

my $py = Inline::Python.new;
$py.run('import datetime');
my $date = $py.call('datetime', 'date', 2017, 1, 31);
$py.call('__builtin__', 'print', $date);    # 2017-01-31
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The arguments that you pass to &lt;code&gt;call&lt;/code&gt; are Perl 6 objects, like three &lt;code&gt;Int&lt;/code&gt;
objects in this example. &lt;code&gt;Inline::Python&lt;/code&gt; automatically translates them to
the corresponding Python built-in data structure. It translate numbers,
strings, arrays and hashes. Return values are also translated in opposite
direction, though since Python 2 does not distinguish properly between
byte and Unicode strings, Python strings end up as buffers in Perl 6.&lt;/p&gt;

&lt;p&gt;Object that &lt;code&gt;Inline::Python&lt;/code&gt; cannot translate are handled as opaque objects
on the Perl 6 side. You can pass them back into python routines (as shown
with the &lt;code&gt;print&lt;/code&gt; call above), or you can also call methods on them:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say $date.isoformat().decode;               # 2017-01-31
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Perl 6 exposes attributes through methods, so Perl 6 has no syntax for
accessing attributes from foreign objects directly. If you try to access
for example the &lt;code&gt;year&lt;/code&gt; attribute of &lt;code&gt;datetime.date&lt;/code&gt; through the normal method call syntax, you get an error.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say $date.year;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Dies with&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'int' object is not callable
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Instead, you have to use the &lt;code&gt;getattr&lt;/code&gt; builtin:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say $py.call('__builtin__', 'getattr', $date, 'year');
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Using the Bridge to Plot&lt;/h2&gt;

&lt;p&gt;We need access to two namespaces in python, &lt;code&gt;datetime&lt;/code&gt; and &lt;code&gt;matplotlib.pyplot&lt;/code&gt;,
so let's start by importing them, and write some short helpers:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $py = Inline::Python.new;
$py.run('import datetime');
$py.run('import matplotlib.pyplot');
sub plot(Str $name, |c) {
    $py.call('matplotlib.pyplot', $name, |c);
}

sub pydate(Str $d) {
    $py.call('datetime', 'date', $d.split('-').map(*.Int));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can now call &lt;code&gt;pydate('2017-03-01')&lt;/code&gt; to create a python &lt;code&gt;datetime.date&lt;/code&gt;
object from an ISO-formatted string, and call the &lt;code&gt;plot&lt;/code&gt; function to access
functionality from matplotlib:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my ($figure, $subplots) = plot('subplots');
$figure.autofmt_xdate();

my @dates = %dates.keys.sort;
$subplots.plot:
    $[@dates.map(&amp;amp;pydate)],
    $[ %dates{@dates} ],
    label     =&amp;gt; 'Total',
    marker    =&amp;gt; '.',
    linestyle =&amp;gt; '';
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Perl 6 call &lt;code&gt;plot('subplots')&lt;/code&gt; corresponds to the python code
&lt;code&gt;fig, subplots = plt.subplots()&lt;/code&gt;. Passing arrays to python function needs
a bit extra work, because &lt;code&gt;Inline::Python&lt;/code&gt; flattens arrays. Using an extra &lt;code&gt;$&lt;/code&gt;
sigil in front of an array puts it into an extra scalar, and thus prevents
the flattening.&lt;/p&gt;

&lt;p&gt;Now we can actually plot the number of commits by author, add a legend, and
plot the result:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;for @top-authors -&amp;gt; $author {
    my @dates = %by-author{$author}.keys.sort;
    my @counts = %by-author{$author}{@dates};
    $subplots.plot:
        $[ @dates.map(&amp;amp;pydate) ],
        $@counts,
        label     =&amp;gt; $author,
        marker    =&amp;gt;'.',
        linestyle =&amp;gt; '';
}


$subplots.legend(loc=&amp;gt;'upper center', shadow=&amp;gt;True);

plot('title', 'Contributions per day');
plot('show');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When run in the &lt;a href=&quot;https://github.com/ugexe/zef&quot;&gt;zef git repository&lt;/a&gt;, it produces
this plot:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://perlgeek.de/images/blog/perl-6/zef-contributors.png&quot; alt=&quot;Contributions to zef, a Perl 6 module installer&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;We've explored how to use the python library matplotlib to generate a plot
from git contribution statistics. &lt;code&gt;Inline::Python&lt;/code&gt; provides convenient
functionality for accessing python libraries from Perl 6 code.&lt;/p&gt;

&lt;p&gt;In the next installment, we'll explore ways to improve both the graphics
and the glue code between Python and Perl 6.&lt;/p&gt;

&lt;div id=&quot;mc_embed_signup&quot;&gt;
&lt;form action=&quot;//perlgeek.us12.list-manage.com/subscribe/post?u=ea4954d15b6283987b9d1b161&amp;amp;id=207c668582&quot; method=&quot;post&quot; id=&quot;mc-embedded-subscribe-form&quot; name=&quot;mc-embedded-subscribe-form&quot; class=&quot;validate&quot; target=&quot;_blank&quot; novalidate&gt;
    &lt;div id=&quot;mc_embed_signup_scroll&quot;&gt;
	&lt;h2&gt;Subscribe to the Perl 6 book mailing list&lt;/h2&gt;
&lt;div class=&quot;indicates-required&quot;&gt;&lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt; indicates required&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-EMAIL&quot;&gt;Email Address  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;email&quot; value=&quot;&quot; name=&quot;EMAIL&quot; class=&quot;required email&quot; id=&quot;mce-EMAIL&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-FNAME&quot;&gt;First Name  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;text&quot; value=&quot;&quot; name=&quot;FNAME&quot; class=&quot;required&quot; id=&quot;mce-FNAME&quot;&gt;
&lt;/div&gt;
	&lt;div id=&quot;mce-responses&quot; class=&quot;clear&quot;&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-error-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-success-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
	&lt;/div&gt;    &lt;!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups--&gt;
    &lt;div style=&quot;position: absolute; left: -5000px;&quot; aria-hidden=&quot;true&quot;&gt;&lt;input type=&quot;text&quot; name=&quot;b_ea4954d15b6283987b9d1b161_207c668582&quot; tabindex=&quot;-1&quot; value=&quot;&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;clear&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;Subscribe&quot; name=&quot;subscribe&quot; id=&quot;mc-embedded-subscribe&quot; class=&quot;button&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'&gt;&lt;/script&gt;&lt;script type='text/javascript'&gt;(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';fnames[1]='FNAME';ftypes[1]='text';}(jQuery));var $mcj = jQuery.noConflict(true);&lt;/script&gt;
&lt;!--End mc_embed_signup--&gt;



</description>
  </item>
  <item>
 <title>What's a Variable, Exactly?</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-011-variable.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Sat, 11 Mar 2017 23:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-03-12 --&gt;

&lt;p&gt;When you learn programming, you typically first learn about basic expressions,
like &lt;code&gt;2 * 21&lt;/code&gt;, and then the next topic is control structures or variables. (If
you start with functional programming, maybe it takes you a bit longer to get
to variables).&lt;/p&gt;

&lt;p&gt;So, every programmer knows what a variable is, right?&lt;/p&gt;

&lt;p&gt;Turns out, it might not be that easy.&lt;/p&gt;

&lt;p&gt;Some people like to say that in ruby, everything is an object. Well, a
variable isn't really an object. The same holds true for other languages.&lt;/p&gt;

&lt;p&gt;But let's start from the bottom up. In a low-level programming language like
C, a local variable is a name that the compiler knows, with a type attached.
When the compiler generates code for the function that the variable is in, the
name resolves to an address on the stack (unless the compiler optimizes the
variable away entirely, or manages it through a CPU register).&lt;/p&gt;

&lt;p&gt;So in C, the variable only exists as such while the compiler is running. When
the compiler is finished, and the resulting executable runs, there might be
some stack offset or memory location that corresponds to our understanding of
the variable. (And there might be debugging symbols that allows some mapping
back to the variable name, but that's really a special case).&lt;/p&gt;

&lt;p&gt;In case of recursion, a local variable can exist once for each time the
function is called.&lt;/p&gt;

&lt;h2&gt;Closures&lt;/h2&gt;

&lt;p&gt;In programming languages with closures, local variables can be referenced from
inner functions. They can't generally live on the stack, because the reference
keeps them alive. Consider this piece of Perl 6 code (though we could write
the same in Javascript, Ruby, Perl 5, Python or most other dynamic languages):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub outer() {
    my $x = 42;
    return sub inner() {
        say $x;
    }
}

my &amp;amp;callback = outer();
callback();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;outer&lt;/code&gt; function has a local (&lt;em&gt;lexical&lt;/em&gt;) variable &lt;code&gt;$x&lt;/code&gt;, and the &lt;code&gt;inner&lt;/code&gt;
function uses it. So once &lt;code&gt;outer&lt;/code&gt; has finished running, there's still an
indirect reference to the value stored in this variable.&lt;/p&gt;

&lt;p&gt;They say you can solve any problem in computer science through another layer
of indirection, and that's true for the implementation of closures. The
&lt;code&gt;&amp;amp;callback&lt;/code&gt; variable, which points to a closure, actually stores two pointers
under the hood. One goes to the static byte code representation of the code,
and the second goes to a run-time data structure called a &lt;em&gt;lexical pad&lt;/em&gt;, or
short &lt;em&gt;lexpad&lt;/em&gt;. Each time you invoke the outer function, a new instance of the
lexpad is created, and the closure points to the new instance, and the always
the same static code.&lt;/p&gt;

&lt;p&gt;But even in dynamic languages with closures, variables themselves don't need
to be objects. If a language forbids the creation of variables at run time,
the compiler knows what variables exist in each scope, and can for example map
each of them to an array index, so the lexpad becomes a compact array, and an
access to a variable becomes an indexing operation into that array. Lexpads
generally live on the heap, and are garbage collected (or reference counted)
just like other objects.&lt;/p&gt;

&lt;p&gt;Lexpads are mostly performance optimizations. You could have separate runtime
representations of each variable, but then you'd have to have an allocation for
each variable in each function call you perform, whereas which are generally
much slower than a single allocation of the lexpad.&lt;/p&gt;

&lt;h2&gt;The Plot Thickens&lt;/h2&gt;

&lt;p&gt;To summarize, a variable has a name, a scope, and in languages that support
it, a type. Those are properties known to the compiler, but not necessarily
present at run time. At run time, a variable typically resolves to a stack
offset in low-level languages, or to an index into a lexpad in dynamic
languages.&lt;/p&gt;

&lt;p&gt;Even in languages that boldly claim that &quot;everything is an object&quot;, a variable
often isn't. The value inside a variable may be, but the variable itself
typically not.&lt;/p&gt;

&lt;h2&gt;Perl 6 Intricacies&lt;/h2&gt;

&lt;p&gt;The things I've written above generalize pretty neatly to many programming
languages. I am a Perl 6 developer, so I have some insight into how
Perl 6 implements variables. If you don't resist, I'll share it with you :-).&lt;/p&gt;

&lt;p&gt;Variables in Perl 6 typically come with one more level of indirection, we
which call a &lt;em&gt;container&lt;/em&gt;. This allows two types of write operations:
&lt;em&gt;assignment&lt;/em&gt; stores a value inside a container (which again might be
referenced to by a variable), and &lt;em&gt;binding&lt;/em&gt;, which places either a value or a
container directly into variable.&lt;/p&gt;

&lt;p&gt;Here's an example of assignment and binding in action:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $x;
my $y;
# assignment:
$x = 42;
$y = 'a string';

say $x;     # =&amp;gt; 42
say $y;     # =&amp;gt; a string

# binding:
$x := $y;

# now $x and $y point to the same container, so that assigning to one
# changes the other:
$y = 21;
say $x;     # =&amp;gt; 21
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Why, I hear you cry?&lt;/p&gt;

&lt;p&gt;There are three major reasons.&lt;/p&gt;

&lt;p&gt;The first is that makes assignment something
that's not special. For example in python, if you assign to anything other
than a plain variable, the compiler translates it to some special method call
(&lt;code&gt;obj.attr = x&lt;/code&gt; to &lt;code&gt;setattr(obj, 'attr', x)&lt;/code&gt;, &lt;code&gt;obj[idx] = x&lt;/code&gt; to a
&lt;code&gt;__setitem__&lt;/code&gt; call etc.). In Perl 6, if you want to implement something you
can assign to, you simply return a container from that expression, and then
assignment works naturally.&lt;/p&gt;

&lt;p&gt;For example an array is basically just a list in which the elements are
containers. This makes &lt;code&gt;@array[$index] = $value&lt;/code&gt; work without any special
cases, and allows you to assign to the return value of methods, functions, or
anything else you can think of, as long as the expression returns a container.&lt;/p&gt;

&lt;p&gt;The second reason for having both binding and assignment is that it makes it
pretty easy to make things read-only. If you bind a non-container into a
variable, you can't assign to it anymore:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $a := 42;
$a = &quot;hordor&quot;;  # =&amp;gt; Cannot assign to an immutable value
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Perl 6 uses this mechanism to make function parameters read-only by default.&lt;/p&gt;

&lt;p&gt;Likewise, returning from a function or method by default strips the container,
which avoids accidental action-at-a-distance (though an &lt;code&gt;is rw&lt;/code&gt; annotation can
prevent that, if you really want it).&lt;/p&gt;

&lt;p&gt;This automatic stripping of containers also makes expressions like &lt;code&gt;$a + 2&lt;/code&gt; work,
independently of whether &lt;code&gt;$a&lt;/code&gt; holds an integer directly, or a container that
holds an integer. (In the implementation of Perl 6's core types, sometimes
this has to be done manually. If you ever wondered what &lt;code&gt;nqp::decont&lt;/code&gt; does in
Rakudo's source code, that's what).&lt;/p&gt;

&lt;p&gt;The third reason relates to types.&lt;/p&gt;

&lt;p&gt;Perl 6 supports gradual typing, which means you can optionally annotate your
variables (and other things) with types, and Perl 6 enforces them for you. It
detects type errors at compile time where possible, and falls back to run-time
checking types.&lt;/p&gt;

&lt;p&gt;The type of a variable only applies to binding, but it inherits this type to
its default container. And the container type is enforced at run time. You can
observe this difference by binding a container with a different constraint:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my Any $x;
my Int $i;
$x := $i;
$x = &quot;foo&quot;;     # =&amp;gt; Type check failed in assignment to $i; expected Int but got Str (&quot;foo&quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;Int&lt;/code&gt; is a subtype of &lt;code&gt;Any&lt;/code&gt;, which is why the binding of &lt;code&gt;$i&lt;/code&gt; to &lt;code&gt;$x&lt;/code&gt;
succeeds. Now &lt;code&gt;$x&lt;/code&gt; and &lt;code&gt;$i&lt;/code&gt; share a container that is type-constrained to
&lt;code&gt;Int&lt;/code&gt;, so assigning a string to it fails.&lt;/p&gt;

&lt;p&gt;Did you notice how the error message mentions &lt;code&gt;$i&lt;/code&gt; as the variable name, even though
we've tried to assign to &lt;code&gt;$x&lt;/code&gt;? The variable name in the error message is really
a heuristic, which works often enough, but sometimes fails. The container
that's shared between &lt;code&gt;$x&lt;/code&gt; and &lt;code&gt;$i&lt;/code&gt; has no idea which variable you used to
access it, it just knows the name of the variable that created it, here &lt;code&gt;$i&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Binding checks the variable type, not the container type, so this code doesn't
complain:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my Any $x;
my Int $i;
$x := $i;
$x := &quot;a string&quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This distinction between variable type and container type might seem weird for
scalar variables, but it really starts to make sense for arrays, hashes and
other compound data structures that might want to enforce a type constraint on
its elements:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub f($x) {
    $x[0] = 7;
}
my Str @s;
f(@s);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This code declares an array whose element all must be of type &lt;code&gt;Str&lt;/code&gt; (or
subtypes thereof). When you pass it to a function, that function has no
compile-time knowledge of the type. But since &lt;code&gt;$x[0]&lt;/code&gt; returns a container with
type constraint &lt;code&gt;Str&lt;/code&gt;, assigning an integer to it can produce the error you
expect from it.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;Variables typically only exists as objects at compile time. At run time, they
are just some memory location, either on the stack or in a lexical pad.&lt;/p&gt;

&lt;p&gt;Perl 6 makes the understanding of the exact nature of variables a bit more
involved by introducing a layer of containers between variables and values.
This offers great flexibility when writing libraries that behaves like
built-in classes, but comes with the burden of additional complexity.&lt;/p&gt;


</description>
  </item>
  <item>
 <title>Perl 6 By Example: A Unicode Search Tool</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-010-unicode.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Sat, 04 Mar 2017 23:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-03-05 --&gt;
&lt;p style=&quot;width: 190; float:right; padding: 10px&quot;&gt;&lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;&lt;img
src=&quot;https://perlgeek.de/images/blog/p6/book-cover-thumbnail.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog post is part of my &lt;a
href=&quot;https://perlgeek.de/blog-en/perl-6/2016-book.html&quot;&gt;ongoing project&lt;/a&gt;
to write a &lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;book about Perl 6&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're interested, either in this book project or any other Perl 6 book news, please sign up for the mailing list at the bottom of
the article, or &lt;a href=&quot;https://perl6book.com/#signup&quot;&gt;here&lt;/a&gt;. It will be
low volume (less than an email per month, on average).&lt;/p&gt;

&lt;hr style=&quot;clear: right&quot; /&gt;


&lt;p&gt;Every so often I have to identify or research some Unicode
characters. There's a tool called &lt;a href=&quot;https://metacpan.org/pod/uni&quot;&gt;uni&lt;/a&gt; in the
Perl 5 distribution &lt;a href=&quot;https://metacpan.org/release/App-Uni&quot;&gt;App::Uni&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's reimplement its basic functionality in a few lines of Perl 6 code and
use that as an occasion to talk about Unicode support in Perl 6.&lt;/p&gt;

&lt;p&gt;If you give it one character on the command line, it prints out a description
of the character:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ uni 🕐
🕐 - U+1f550 - CLOCK FACE ONE OCLOCK
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you give it a longer string instead, it searches in the list of Unicode
character names and prints out the same information for each character whose
description matches the search string:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ uni third|head -n5
⅓ - U+02153 - VULGAR FRACTION ONE THIRD
⅔ - U+02154 - VULGAR FRACTION TWO THIRDS
↉ - U+02189 - VULGAR FRACTION ZERO THIRDS
㆛ - U+0319b - IDEOGRAPHIC ANNOTATION THIRD MARK
𐄺 - U+1013a - AEGEAN WEIGHT THIRD SUBUNIT
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Each line corresponds to what Unicode calls a &quot;code point&quot;, which is usually a
character on its own, but occasionally also something like a &lt;code&gt;U+00300 -
COMBINING GRAVE ACCENT&lt;/code&gt;, which, combined with a &lt;code&gt;a - U+00061 - LATIN SMALL
LETTER A&lt;/code&gt; makes the character &lt;code&gt;à&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Perl 6 offers a method &lt;code&gt;uniname&lt;/code&gt; in both the classes &lt;code&gt;Str&lt;/code&gt; and &lt;code&gt;Int&lt;/code&gt; that
produces the Unicode code point name for a given character, either in its
direct character form, or in the form the code point number. With that, the
first part of &lt;code&gt;uni&lt;/code&gt;'s desired functionality:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/env perl6

use v6;

sub format-codepoint(Int $codepoint) {
    sprintf &quot;%s - U+%05x - %s\n&quot;,
        $codepoint.chr,
        $codepoint,
        $codepoint.uniname;
}

multi sub MAIN(Str $x where .chars == 1) {
    print format-codepoint($x.ord);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let's look at it in action:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ uni ø
ø - U+000f8 - LATIN SMALL LETTER O WITH STROKE
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;chr&lt;/code&gt; method turns a code point number into the character and &lt;code&gt;ord&lt;/code&gt; is
the reverse, in other words: from character to code point number.&lt;/p&gt;

&lt;p&gt;The second part, searching in all Unicode character names, works by
brute-force enumerating all possible characters and searching through their
&lt;code&gt;uniname&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;multi sub MAIN($search is copy) {
    $search.=uc;
    for 1..0x10FFFF -&amp;gt; $codepoint {
        if $codepoint.uniname.contains($search) {
            print format-codepoint($codepoint);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since all character names are in upper case, the search term is first
converted to upper case with &lt;code&gt;$search.=uc&lt;/code&gt;, which is short for &lt;code&gt;$search =
$search.uc&lt;/code&gt;. By default, parameters are read only, which is why its
declaration here uses &lt;code&gt;is copy&lt;/code&gt; to prevent that.&lt;/p&gt;

&lt;p&gt;Instead of this rather imperative style, we can also formulate it in a more
functional style. We could think of it as a list of all characters, which we
whittle down to those characters that interest us, to finally format them
the way we want:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;multi sub MAIN($search is copy) {
    $search.=uc;
    print (1..0x10FFFF).grep(*.uniname.contains($search))
                       .map(&amp;amp;format-codepoint)
                       .join;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To make it easier to identify (rather than search for) a string of more than
one character, an explicit option can help disambiguate:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;multi sub MAIN($x, Bool :$identify!) {
    print $x.ords.map(&amp;amp;format-codepoint).join;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;Str.ords&lt;/code&gt; returns the list of code points that make up the string. With this
multi candidate of sub &lt;code&gt;MAIN&lt;/code&gt; in place, we can do something like&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ uni --identify øre
ø - U+000f8 - LATIN SMALL LETTER O WITH STROKE
r - U+00072 - LATIN SMALL LETTER R
e - U+00065 - LATIN SMALL LETTER E
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Code Points, Grapheme Clusters and Bytes&lt;/h2&gt;

&lt;p&gt;As alluded to above, not all code points are fully-fledged characters on their
own. Or put another way, some things that we visually identify as a single
character are actually made up of several code points. Unicode calls these
sequences of one base character and potentially several combining characters as a
&lt;em&gt;grapheme cluster&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Strings in Perl 6 are based on these grapheme clusters. If you get a list of
characters in string with &lt;code&gt;$str.comb&lt;/code&gt;, or extract a substring with
&lt;code&gt;$str.substr(0, 4)&lt;/code&gt;, match a regex against a string, determine the length, or
do any other operation on a string, the unit is always the grapheme cluster.
This best fits our intuitive understanding of what a character is and avoids
accidentally tearing apart a logical character through a &lt;code&gt;substr&lt;/code&gt;, &lt;code&gt;comb&lt;/code&gt; or
similar operation:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $s = &quot;ø\c[COMBINING TILDE]&quot;;
say $s;         # ø̃
say $s.chars;   # 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;a href=&quot;https://docs.perl6.org/type/Uni&quot;&gt;Uni&lt;/a&gt; type is akin to a string and
represents a sequence of codepoints. It is useful in edge cases, but doesn't
support the same wealth of operations as
&lt;a href=&quot;https://docs.perl6.org/type/Str&quot;&gt;Str&lt;/a&gt;. The typical way to go from &lt;code&gt;Str&lt;/code&gt; to a
&lt;code&gt;Uni&lt;/code&gt; value is to use one of the &lt;code&gt;NFC&lt;/code&gt;, &lt;code&gt;NFD&lt;/code&gt;, &lt;code&gt;NFKC&lt;/code&gt;, or &lt;code&gt;NFKD&lt;/code&gt; methods, which
yield a &lt;code&gt;Uni&lt;/code&gt; value in the normalization form of the same name.&lt;/p&gt;

&lt;p&gt;Below the &lt;code&gt;Uni&lt;/code&gt; level you can also represent strings as bytes by choosing an
encoding. If you want to get from string to the byte level, call the
&lt;a href=&quot;https://docs.perl6.org/type/Str#method_encode&quot;&gt;&lt;code&gt;encode&lt;/code&gt;&lt;/a&gt; method:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my $bytes = 'Perl 6'.encode('UTF-8');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;UTF-8 is the default encoding and also the one Perl 6 assumes when reading
source files. The result is something that does the
&lt;a href=&quot;https://docs.perl6.org/type/Blob.html&quot;&gt;Blob&lt;/a&gt; role; you can access
individual bytes with positional indexing, such as &lt;code&gt;$bytes[0]&lt;/code&gt;. The
&lt;a href=&quot;https://docs.perl6.org/type/Blob.html#method_decode&quot;&gt;&lt;code&gt;decode&lt;/code&gt; method&lt;/a&gt; helps
you to convert a &lt;code&gt;Blob&lt;/code&gt; to a &lt;code&gt;Str&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Numbers&lt;/h2&gt;

&lt;p&gt;Number literals in Perl 6 aren't limited to the Arabic digits we are so used
to in the English speaking part of the world. All Unicode code points that
have the &lt;code&gt;Decimal_Number&lt;/code&gt; (short &lt;code&gt;Nd&lt;/code&gt;) property are allowed, so you can for
example use Bengali digits:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say ৪২;             # 42
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The same holds true for string to number conversions:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say &quot;৪২&quot;.Int;       # 42
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For other numeric code points you can use the &lt;code&gt;unival&lt;/code&gt; method to obtain its
numeric value:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say &quot;\c[TIBETAN DIGIT HALF ZERO]&quot;.unival;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which produces the output &lt;code&gt;-0.5&lt;/code&gt; and also illustrates how to use a codepoint
by name inside a string literal.&lt;/p&gt;

&lt;h2&gt;Other Unicode Properties&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://docs.perl6.org/type/Str#(Cool)_method_uniprop&quot;&gt;&lt;code&gt;uniprop&lt;/code&gt; method&lt;/a&gt;
in type &lt;code&gt;Str&lt;/code&gt; returns the general category by default:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say &quot;ø&quot;.uniprop;                            # Ll
say &quot;\c[TIBETAN DIGIT HALF ZERO]&quot;.uniprop;  # No
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The return value needs some Unicode knowledge in order to make sense of it,
or one could read
&lt;a href=&quot;http://unicode.org/reports/tr44/#Properties&quot;&gt;Unicode's Technical Report 44&lt;/a&gt; for the gory details.
&lt;code&gt;Ll&lt;/code&gt; stands for &lt;code&gt;Letter_Lowercase&lt;/code&gt;, &lt;code&gt;No&lt;/code&gt; is &lt;code&gt;Other_Number&lt;/code&gt;. This is what
Unicode calls the &lt;em&gt;General Category&lt;/em&gt;, but you can ask the &lt;code&gt;uniprop&lt;/code&gt; (or
&lt;code&gt;uniprop-bool&lt;/code&gt; method if you're only interested in a boolean result) for
other properties as well:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;say &quot;a&quot;.uniprop-bool('ASCII_Hex_Digit');    # True
say &quot;ü&quot;.uniprop-bool('Numeric_Type');       # False
say &quot;.&quot;.uniprop(&quot;Word_Break&quot;);              # MidNumLet
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Collation&lt;/h2&gt;

&lt;p&gt;Sorting strings starts to become complicated when you're not limited to ASCII
characters. Perl 6's &lt;code&gt;sort&lt;/code&gt; method uses the &lt;code&gt;cmp&lt;/code&gt; infix operator, which does a
pretty standard lexicographic comparison based on the codepoint number.&lt;/p&gt;

&lt;p&gt;If you need to use a more
sophisticated collation algorithm, Rakudo 2017.02 and newer offer the
&lt;a href=&quot;http://unicode.org/reports/tr10/&quot;&gt;Unicode Collation Algorithm&lt;/a&gt; as an
experimental feature:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @list = &amp;lt;a ö ä Ä o ø&amp;gt;;
say @list.sort;                     # (a o Ä ä ö ø)

use experimental :collation;
say @list.collate;                  # (a ä Ä o ö ø)
$*COLLATION.set(:tertiary(False));
say @list.collate;                  # (a Ä ä o ö ø)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The default &lt;code&gt;sort&lt;/code&gt; considers any character with diacritics to be larger than
ASCII characters, because that's how they appear in the code point list. On
the other hand, &lt;code&gt;collate&lt;/code&gt; knows that characters with diacritics belong
directly after their base character, which is not perfect in every language,
but internally a good compromise.&lt;/p&gt;

&lt;p&gt;For Latin-based scripts, the primary sorting criteria is alphabetic, the
secondary diacritics, and the third is case.
&lt;code&gt;$*COLLATION.set(:tertiary(False))&lt;/code&gt; thus makes &lt;code&gt;.collate&lt;/code&gt; ignore case, so it
doesn't force lower case characters to come before upper case characters
anymore.&lt;/p&gt;

&lt;p&gt;At the time of writing, language specification of collation is not yet
implemented.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;Perl 6 takes languages other than English very seriously, and goes to great
lengths to facilitate working with them and the characters they use.&lt;/p&gt;

&lt;p&gt;This includes basing strings on grapheme clusters rather than code points,
support for non-Arabic digits in numbers, and access to large parts of Unicode
database through built-in methods.&lt;/p&gt;

&lt;div id=&quot;mc_embed_signup&quot;&gt;
&lt;form action=&quot;//perlgeek.us12.list-manage.com/subscribe/post?u=ea4954d15b6283987b9d1b161&amp;amp;id=207c668582&quot; method=&quot;post&quot; id=&quot;mc-embedded-subscribe-form&quot; name=&quot;mc-embedded-subscribe-form&quot; class=&quot;validate&quot; target=&quot;_blank&quot; novalidate&gt;
    &lt;div id=&quot;mc_embed_signup_scroll&quot;&gt;
	&lt;h2&gt;Subscribe to the Perl 6 book mailing list&lt;/h2&gt;
&lt;div class=&quot;indicates-required&quot;&gt;&lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt; indicates required&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-EMAIL&quot;&gt;Email Address  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;email&quot; value=&quot;&quot; name=&quot;EMAIL&quot; class=&quot;required email&quot; id=&quot;mce-EMAIL&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-FNAME&quot;&gt;First Name  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;text&quot; value=&quot;&quot; name=&quot;FNAME&quot; class=&quot;required&quot; id=&quot;mce-FNAME&quot;&gt;
&lt;/div&gt;
	&lt;div id=&quot;mce-responses&quot; class=&quot;clear&quot;&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-error-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-success-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
	&lt;/div&gt;    &lt;!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups--&gt;
    &lt;div style=&quot;position: absolute; left: -5000px;&quot; aria-hidden=&quot;true&quot;&gt;&lt;input type=&quot;text&quot; name=&quot;b_ea4954d15b6283987b9d1b161_207c668582&quot; tabindex=&quot;-1&quot; value=&quot;&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;clear&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;Subscribe&quot; name=&quot;subscribe&quot; id=&quot;mc-embedded-subscribe&quot; class=&quot;button&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'&gt;&lt;/script&gt;&lt;script type='text/javascript'&gt;(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';fnames[1]='FNAME';ftypes[1]='text';}(jQuery));var $mcj = jQuery.noConflict(true);&lt;/script&gt;
&lt;!--End mc_embed_signup--&gt;



</description>
  </item>
  <item>
 <title>Perl 6 By Example: Functional Refactorings for Directory Visualization Code</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-009-functional-refactorings.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Sat, 25 Feb 2017 23:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-02-26 --&gt;
&lt;p style=&quot;width: 190; float:right; padding: 10px&quot;&gt;&lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;&lt;img
src=&quot;https://perlgeek.de/images/blog/p6/book-cover-thumbnail.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog post is part of my &lt;a
href=&quot;https://perlgeek.de/blog-en/perl-6/2016-book.html&quot;&gt;ongoing project&lt;/a&gt;
to write a &lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;book about Perl 6&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're interested, either in this book project or any other Perl 6 book news, please sign up for the mailing list at the bottom of
the article, or &lt;a href=&quot;https://perl6book.com/#signup&quot;&gt;here&lt;/a&gt;. It will be
low volume (less than an email per month, on average).&lt;/p&gt;

&lt;hr style=&quot;clear: right&quot; /&gt;


&lt;p&gt;In the &lt;a href=&quot;https://perlgeek.de/blog-en/perl-6/2017-008-file-directory-usage-graph.html&quot;&gt;last installment&lt;/a&gt; we've seen some code that generated tree maps
and flame graphs from a tree of directory and file sizes.&lt;/p&gt;

&lt;p&gt;There's a pattern that occurs three times in that code: dividing an area
based on the size of the files and directories in the tree associated with the
area.&lt;/p&gt;

&lt;p&gt;Extracting such common code into a function is a good idea, but it's slightly
hindered by the fact that there is custom code inside the loop that's part of
the common code. Functional programming offers a solution: Put the custom code
inside a separate function and have the common code call it.&lt;/p&gt;

&lt;p&gt;Applying this technique to the tree graph flame graph looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub subdivide($tree, $lower, $upper, &amp;amp;todo) {
    my $base = ($upper - $lower ) / $tree.total-size;
    my $var  = $lower;
    for $tree.children -&amp;gt; $child {
        my $incremented = $var + $base * $child.total-size;
        todo($child, $var, $incremented);
        $var = $incremented,
    }
}

sub flame-graph($tree, :$x1!, :$x2!, :$y!, :$height!) {
    return if $y &amp;gt;= $height;
    take 'rect' =&amp;gt; [
        x      =&amp;gt; $x1,
        y      =&amp;gt; $y,
        width  =&amp;gt; $x2 - $x1,
        height =&amp;gt; 15,
        style  =&amp;gt; &quot;fill:&quot; ~ random-color(),
        title  =&amp;gt; [$tree.name ~ ', ' ~ format-size($tree.total-size)],
    ];
    return if $tree ~~ File;
    subdivide( $tree, $x1, $x2, -&amp;gt; $child, $x1, $x2 {
        flame-graph( $child, :$x1, :$x2, :y($y + 15), :$height );
    });
}

sub tree-map($tree, :$x1!, :$x2!, :$y1!, :$y2) {
    return if ($x2 - $x1) * ($y2 - $y1) &amp;lt; 20;
    take 'rect' =&amp;gt; [
        x      =&amp;gt; $x1,
        y      =&amp;gt; $y1,
        width  =&amp;gt; $x2 - $x1,
        height =&amp;gt; $y2 - $y1,
        style  =&amp;gt; &quot;fill:&quot; ~ random-color(),
        title  =&amp;gt; [$tree.name],
    ];
    return if $tree ~~ File;

    if $x2 - $x1 &amp;gt; $y2 - $y1 {
        # split along the x-axis
        subdivide $tree, $x1, $x2, -&amp;gt; $child, $x1, $x2 {
            tree-map $child, :$x1, :$x2, :$y1, :$y2;
        }
    }
    else {
        # split along the y-axis
        subdivide $tree, $y1, $y2, -&amp;gt; $child, $y1, $y2 {
            tree-map $child, :$x1, :$x2, :$y1, :$y2;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The newly introduced subroutine &lt;code&gt;subdivide&lt;/code&gt; takes a directory tree, a start
point and an end point, and finally a code object &lt;code&gt;&amp;amp;todo&lt;/code&gt;. For each child of
the directory tree it calculates the new coordinates and then calls the
&lt;code&gt;&amp;amp;todo&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;The usage in subroutine &lt;code&gt;flame-graph&lt;/code&gt; looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;subdivide( $tree, $x1, $x2, -&amp;gt; $child, $x1, $x2 {
flame-graph( $child, :$x1, :$x2, :y($y + 15), :$height );
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The code object being passed to &lt;code&gt;subdivide&lt;/code&gt; starts with &lt;code&gt;-&amp;gt;&lt;/code&gt;,
which introduces the signature of a block. The code block recurses into
&lt;code&gt;flame-graph&lt;/code&gt;, adding some extra arguments, and turning two positional
arguments into named arguments along the way.&lt;/p&gt;

&lt;p&gt;This refactoring shortened the code and made it overall more pleasant to work
with. But there's still quite a bit of duplication between &lt;code&gt;tree-map&lt;/code&gt; and
&lt;code&gt;flame-graph&lt;/code&gt;: both have an initial termination condition, a &lt;code&gt;take&lt;/code&gt; of a
rectangle, and then a call or two to &lt;code&gt;subdivide&lt;/code&gt;. If we're willing to put all
the small differences into small, separate functions, we can unify it further.&lt;/p&gt;

&lt;p&gt;If we pass all those new functions as arguments to each call, we create an
unpleasantly long argument list. Instead, we can use those functions to
generate the previous functions &lt;code&gt;flame-graph&lt;/code&gt; and &lt;code&gt;tree-map&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub svg-tree-gen(:&amp;amp;terminate!, :&amp;amp;base-height!, :&amp;amp;subdivide-x!, :&amp;amp;other!) {
    sub inner($tree, :$x1!, :$x2!, :$y1!, :$y2!) {
        return if terminate(:$x1, :$x2, :$y1, :$y2);
        take 'rect' =&amp;gt; [
            x      =&amp;gt; $x1,
            y      =&amp;gt; $y1,
            width  =&amp;gt; $x2 - $x1,
            height =&amp;gt; base-height(:$y1, :$y2),
            style  =&amp;gt; &quot;fill:&quot; ~ random-color(),
            title  =&amp;gt; [$tree.name ~ ', ' ~ format-size($tree.total-size)],
        ];
        return if $tree ~~ File;
        if subdivide-x(:$x1, :$y1, :$x2, :$y2) {
            # split along the x-axis
            subdivide $tree, $x1, $x2, -&amp;gt; $child, $x1, $x2 {
                inner($child, :$x1, :$x2, :y1(other($y1)), :$y2);
            }
        }
        else {
            # split along the y-axis
            subdivide $tree, $y1, $y2, -&amp;gt; $child, $y1, $y2 {
                inner($child, :x1(other($x1)), :$x2, :$y1, :$y2);
            }
        }
    }
}

my &amp;amp;flame-graph = svg-tree-gen
    terminate   =&amp;gt; -&amp;gt; :$y1, :$y2, | { $y1 &amp;gt; $y2 },
    base-height =&amp;gt; -&amp;gt; | { 15 },
    subdivide-x =&amp;gt; -&amp;gt; | { True },
    other       =&amp;gt; -&amp;gt; $y1 { $y1 + 15 },

my &amp;amp;tree-map = svg-tree-gen
    terminate   =&amp;gt; -&amp;gt; :$x1, :$y1, :$x2, :$y2 { ($x2 - $x1) * ($y2 - $y1) &amp;lt; 20 },
    base-height =&amp;gt; -&amp;gt; :$y1, :$y2 {  $y2 - $y1 },
    subdivide-x =&amp;gt; -&amp;gt; :$x1, :$x2, :$y1, :$y2 { $x2 - $x1 &amp;gt; $y2 - $y1 },
    other       =&amp;gt; -&amp;gt; $a { $a },
    ;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So there's a new function &lt;code&gt;svg-tree-gen&lt;/code&gt;, which returns a function. The
behavior of the returned function depends on the four small functions that
&lt;code&gt;svg-tree-gen&lt;/code&gt; receives as arguments.&lt;/p&gt;

&lt;p&gt;The first argument, &lt;code&gt;terminate&lt;/code&gt;, determines
under what condition the inner function should terminate early. For &lt;code&gt;tree-map&lt;/code&gt;
that's when the area is below 20 pixels, for &lt;code&gt;flame-graph&lt;/code&gt; when the current
y-coordinate &lt;code&gt;$y1&lt;/code&gt; exceeds the height of the whole image, which is stored in
&lt;code&gt;$y2&lt;/code&gt;. &lt;code&gt;svg-tree-gen&lt;/code&gt; always calls this function with the four named arguments
&lt;code&gt;x1&lt;/code&gt;, &lt;code&gt;x2&lt;/code&gt;, &lt;code&gt;y1&lt;/code&gt; and &lt;code&gt;y2&lt;/code&gt;, so the &lt;code&gt;terminate&lt;/code&gt; function must ignore the &lt;code&gt;x1&lt;/code&gt;
and &lt;code&gt;x2&lt;/code&gt; values. It does this by adding &lt;code&gt;|&lt;/code&gt; as a parameter, which is an
anonymous capture. Such a parameter can bind arbitrary positional and named
arguments, and since it's an anonymous parameter, it discards all the values.&lt;/p&gt;

&lt;p&gt;The second configuration function, &lt;code&gt;base-height&lt;/code&gt;, determines the height of the
rectangle in the base case. For &lt;code&gt;flame-graph&lt;/code&gt; it's a constant, so the
configuration function must discard all arguments, again with a &lt;code&gt;|&lt;/code&gt;. For
&lt;code&gt;tree-graph&lt;/code&gt;, it must return the difference between &lt;code&gt;$y2&lt;/code&gt; and &lt;code&gt;$y1&lt;/code&gt;, as before
the refactoring.&lt;/p&gt;

&lt;p&gt;The third function determines when to subdivide along the x-axis. Flame graphs
always divide along the x-axis, so &lt;code&gt;-&amp;gt; | { True }&lt;/code&gt; accomplishes that. Our
simplistic approach to tree graphs divides along the longer axis, so only
along the x-axis if &lt;code&gt;$x2 - $x1 &amp;gt; $y2 - $y1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The fourth and final function we pass to &lt;code&gt;svg-tree-gen&lt;/code&gt; calculates the
coordinate of the axis that isn't being subdivided. In the case of
&lt;code&gt;flame-graph&lt;/code&gt; that's increasing over the previous value by the height of the
bars, and for &lt;code&gt;tree-map&lt;/code&gt; it's the unchanged coordinate, so we pass the
identity function &lt;code&gt;-&amp;gt; $a { $a }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The inner function only needs a name because we need to call it from itself
recursively; otherwise an anonymous function &lt;code&gt;sub ($tree,  :$x1!, :$x2!,
:$y1!, :$y2!) { ... }&lt;/code&gt; would have worked fine.&lt;/p&gt;

&lt;p&gt;Now that we have very compact definitions of &lt;code&gt;flame-graph&lt;/code&gt; and &lt;code&gt;tree-map&lt;/code&gt;,
it's a good time to play with some of the parameters. For example we can
introduce a bit of margin in the flame graph by having the increment in
&lt;code&gt;other&lt;/code&gt; greater than the bar height in &lt;code&gt;base-height&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my &amp;amp;flame-graph = svg-tree-gen
    base-height =&amp;gt; -&amp;gt; | { 15 },
    other       =&amp;gt; -&amp;gt; $y1 { $y1 + 16 },
    # rest as before
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another knob to turn is to change the color generation to something more
deterministic, and make it configurable from the outside:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub svg-tree-gen(:&amp;amp;terminate!, :&amp;amp;base-height!, :&amp;amp;subdivide-x!, :&amp;amp;other!,
                 :&amp;amp;color=&amp;amp;random-color) {
    sub inner($tree, :$x1!, :$x2!, :$y1!, :$y2!) {
        return if terminate(:$x1, :$x2, :$y1, :$y2);
        take 'rect' =&amp;gt; [
            x      =&amp;gt; $x1,
            y      =&amp;gt; $y1,
            width  =&amp;gt; $x2 - $x1,
            height =&amp;gt; base-height(:$y1, :$y2),
            style  =&amp;gt; &quot;fill:&quot; ~ color(:$x1, :$x2, :$y1, :$y2),
            title  =&amp;gt; [$tree.name ~ ', ' ~ format-size($tree.total-size)],
        ];
        # rest as before
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can, for example, keep state within the color generator and return a
slightly different color during each iteration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub color-range(|) {
    state ($r, $g, $b) = (0, 240, 120);
    $r = ($r + 5) % 256;
    $g = ($g + 10) % 256;
    $b = ($b + 15) % 256;
    return &quot;rgb($r,$g,$b)&quot;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;state&lt;/code&gt; variables keep their values between calls to the same subroutine and
their initialization runs only on the first call. So this function slightly
increases the lightness in each color channel for each invocation, except
when it reaches 256, where the modulo operator &lt;code&gt;%&lt;/code&gt; resets it back to a small
value.&lt;/p&gt;

&lt;p&gt;If we plug this into our functions by passing &lt;code&gt;color =&amp;gt; &amp;amp;color-range&lt;/code&gt; to the
calls to &lt;code&gt;svg-tree-gen&lt;/code&gt;, we get much less chaotic looking output:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://perlgeek.de/images/blog/perl-6/box-color.png&quot; alt=&quot;Tree map with deterministic color generation&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And the flame graph:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://perlgeek.de/images/blog/perl-6/flame-color.png&quot; alt=&quot;Flame graph with deterministic color generation and one pixel margin between
bars&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;More Language Support for Functional Programming&lt;/h2&gt;

&lt;p&gt;As you've seen in the examples above, functional programming typically
involves writing lots of small functions. Perl 6 has some language features
that make it very easy to write such small functions.&lt;/p&gt;

&lt;p&gt;A common task is to write a function that calls a particular method on its
argument, as we've seen here:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;method total-size() {
    $!total-size //= $.size + @.children.map({.total-size}).sum;
    #                                        ^^^^^^^^^^^^^
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This can be abbreviated to &lt;code&gt;*.total-size&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;method total-size() {
    $!total-size //= $.size + @.children.map(*.total-size).sum;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This works for chains of method calls too, so you could write
&lt;code&gt;@.children.map(*.total-size.round)&lt;/code&gt; if &lt;code&gt;total-size&lt;/code&gt; returned a fractional
number and you wanted to the call &lt;code&gt;.round&lt;/code&gt; method on the result.&lt;/p&gt;

&lt;p&gt;There are more cases where you can replace an expression with the &quot;Whatever&quot;
star &lt;code&gt;*&lt;/code&gt; to create a small function. To create a function that adds 15 to its
argument, you can write &lt;code&gt;* + 15&lt;/code&gt; instead of &lt;code&gt;-&amp;gt; $a { $a + 15 }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you need to write a function to just call another function, but pass more
arguments to the second function, you can use the method
&lt;a href=&quot;https://docs.perl6.org/routine/assuming&quot;&gt;assuming&lt;/a&gt;. For example &lt;code&gt;-&amp;gt; $x {
f(42, $x }&lt;/code&gt; can be replaced with &lt;code&gt;&amp;amp;f.assuming(42)&lt;/code&gt;. This works also for named
arguments, so &lt;code&gt;-&amp;gt; $x { f($x, height =&amp;gt; 42 ) }&lt;/code&gt; can be replaced with
&lt;code&gt;&amp;amp;f.assuming(height =&amp;gt; 42)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;Functional programming offers techniques for extracting common logic into
separate functions. The desired differences in behavior can be encoded in more
functions that you pass in as arguments to other functions.&lt;/p&gt;

&lt;p&gt;Perl 6 supports functional programming by making functions first class, so you
can pass them around as ordinary objects. It also offers closures (access to
outer lexical variables from functions), and various shortcuts that make it
more pleasant to write short functions.&lt;/p&gt;

&lt;div id=&quot;mc_embed_signup&quot;&gt;
&lt;form action=&quot;//perlgeek.us12.list-manage.com/subscribe/post?u=ea4954d15b6283987b9d1b161&amp;amp;id=207c668582&quot; method=&quot;post&quot; id=&quot;mc-embedded-subscribe-form&quot; name=&quot;mc-embedded-subscribe-form&quot; class=&quot;validate&quot; target=&quot;_blank&quot; novalidate&gt;
    &lt;div id=&quot;mc_embed_signup_scroll&quot;&gt;
	&lt;h2&gt;Subscribe to the Perl 6 book mailing list&lt;/h2&gt;
&lt;div class=&quot;indicates-required&quot;&gt;&lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt; indicates required&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-EMAIL&quot;&gt;Email Address  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;email&quot; value=&quot;&quot; name=&quot;EMAIL&quot; class=&quot;required email&quot; id=&quot;mce-EMAIL&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-FNAME&quot;&gt;First Name  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;text&quot; value=&quot;&quot; name=&quot;FNAME&quot; class=&quot;required&quot; id=&quot;mce-FNAME&quot;&gt;
&lt;/div&gt;
	&lt;div id=&quot;mce-responses&quot; class=&quot;clear&quot;&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-error-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-success-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
	&lt;/div&gt;    &lt;!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups--&gt;
    &lt;div style=&quot;position: absolute; left: -5000px;&quot; aria-hidden=&quot;true&quot;&gt;&lt;input type=&quot;text&quot; name=&quot;b_ea4954d15b6283987b9d1b161_207c668582&quot; tabindex=&quot;-1&quot; value=&quot;&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;clear&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;Subscribe&quot; name=&quot;subscribe&quot; id=&quot;mc-embedded-subscribe&quot; class=&quot;button&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'&gt;&lt;/script&gt;&lt;script type='text/javascript'&gt;(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';fnames[1]='FNAME';ftypes[1]='text';}(jQuery));var $mcj = jQuery.noConflict(true);&lt;/script&gt;
&lt;!--End mc_embed_signup--&gt;



</description>
  </item>
  <item>
 <title>Perl 6 By Example: A File and Directory Usage Graph</title>
  <link>http://perlgeek.de/blog-en/perl-6/2017-008-file-directory-usage-graph.html</link>
 <author>Moritz Lenz</author>
   <pubDate>Sat, 18 Feb 2017 23:00:01 +0100</pubDate>
    <description>&lt;!-- 2017-02-19 --&gt;
&lt;p style=&quot;width: 190; float:right; padding: 10px&quot;&gt;&lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;&lt;img
src=&quot;https://perlgeek.de/images/blog/p6/book-cover-thumbnail.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog post is part of my &lt;a
href=&quot;https://perlgeek.de/blog-en/perl-6/2016-book.html&quot;&gt;ongoing project&lt;/a&gt;
to write a &lt;a href=&quot;https://leanpub.com/perl6&quot;&gt;book about Perl 6&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're interested, either in this book project or any other Perl 6 book news, please sign up for the mailing list at the bottom of
the article, or &lt;a href=&quot;https://perl6book.com/#signup&quot;&gt;here&lt;/a&gt;. It will be
low volume (less than an email per month, on average).&lt;/p&gt;

&lt;hr style=&quot;clear: right&quot; /&gt;


&lt;h1&gt;A File and Directory Usage Graph&lt;/h1&gt;

&lt;p&gt;You bought a shiny new 2TB disk just a short while ago, and you're already
getting low disk space warnings. What's taking up all that space?&lt;/p&gt;

&lt;p&gt;To answer this question, and experiment a bit with data visualization,
let's write a small tool that visualizes which files use up how much disk
space.&lt;/p&gt;

&lt;p&gt;To do that, we must first recursively read all directories and files in a
given directory, and record their sizes. To get a listing of all elements in a
directory, we can use the &lt;a href=&quot;https://docs.perl6.org/routine/dir&quot;&gt;dir&lt;/a&gt; function,
which returns a lazy list of
&lt;a href=&quot;https://docs.perl6.org/type/IO$COLON$COLONPath&quot;&gt;IO::Path&lt;/a&gt; objects.&lt;/p&gt;

&lt;p&gt;We distinguish between directories, which can have child entries, and files,
which don't. Both can have a direct size, and in the case of directories also
a total size, which includes files and subdirectories, recursively:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class File {
    has $.name;
    has $.size;
    method total-size() { $.size }
}

class Directory {
    has $.name;
    has $.size;
    has @.children;
    has $!total-size;
    method total-size() {
        $!total-size //= $.size + @.children.map({.total-size}).sum;
    }
}

sub tree(IO::Path $path) {
    if $path.d {
        return Directory.new(
            name     =&amp;gt; $path.basename,
            size     =&amp;gt; $path.s,
            children =&amp;gt; dir($path).map(&amp;amp;tree),
        );
    }
    else {
        return File.new(
            name =&amp;gt; $path.Str,
            size =&amp;gt; $path.s,
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Method &lt;code&gt;total-size&lt;/code&gt; in class &lt;code&gt;Directory&lt;/code&gt; uses the construct &lt;code&gt;$var //= EXPR´.
The&lt;/code&gt;//&lt;code&gt;stands for *defined-OR*, so it returns the left-hand side if it has a
defined value. Otherwise, it evalutes and returns the value of&lt;/code&gt;EXPR`.
Combined with the assignment operator, it evaluates the right-hand side only
if the variable is undefined, and then stores the value of the expression in
the variable. That's a short way to write a cache.&lt;/p&gt;

&lt;p&gt;The code for reading a file tree recursively uses the &lt;code&gt;d&lt;/code&gt; and &lt;code&gt;s&lt;/code&gt; methods on
&lt;code&gt;IO::Path&lt;/code&gt;. &lt;code&gt;d&lt;/code&gt; returns True for directories, and false for files. &lt;code&gt;s&lt;/code&gt; returns
the size. (Note that &lt;code&gt;.s&lt;/code&gt; on directories used to throw an exception in older
Rakudo versions. You must use Rakudo 2017.01-169 or newer for this to work; if
you are stuck on an older version of Rakudo, you could hard code the size of a
directory to a typical block size, like 4096 bytes. It typically won't skew
your results too much).&lt;/p&gt;

&lt;p&gt;Just to check that we've got a sensible data structure, we can write a short
routine that prints it recursively, with indention to indicate nesting of
directory entries:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub print-tree($tree, Int $indent = 0) {
    say ' ' x $indent, format-size($tree.total-size), '  ', $tree.name;
    if $tree ~~ Directory {
        print-tree($_, $indent + 2) for $tree.children
    }
}

sub format-size(Int $bytes) {
    my @units = flat '', &amp;lt;k M G T P&amp;gt;;
    my @steps = (1, { $_ * 1024 } ... *).head(6);
    for @steps.kv -&amp;gt; $idx, $step {
        my $in-unit = $bytes / $step;
        if $in-unit &amp;lt; 1024 {
            return sprintf '%.1f%s', $in-unit, @units[$idx];
        }
    }
}

sub MAIN($dir = '.') {
    print-tree(tree($dir.IO));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The subroutine &lt;code&gt;print-tree&lt;/code&gt; is pretty boring, if you're used to recursion. It
prins out the name and size of the current node, and if the current node is a
directory, recurses into each children with an increased indention. The
indention is applied through the &lt;code&gt;x&lt;/code&gt; string repetition operator, which when
called as &lt;code&gt;$string x $count&lt;/code&gt; repeates the &lt;code&gt;$string&lt;/code&gt; for &lt;code&gt;$count&lt;/code&gt; times.&lt;/p&gt;

&lt;p&gt;To get a human-readable repretation of the size of a number, &lt;code&gt;format-size&lt;/code&gt;
knows a list of six units: the empty string for one, &lt;code&gt;k&lt;/code&gt; (kilo) for 1024, &lt;code&gt;M&lt;/code&gt;
(mega) for 1024*1024 and so on. This list is stored in the array &lt;code&gt;@units&lt;/code&gt;. The
multiplies assoziated with each unit is stored in &lt;code&gt;@steps&lt;/code&gt;, which is
iniitliazed through the &lt;em&gt;series&lt;/em&gt; operator. &lt;code&gt;...&lt;/code&gt;. Its structure is
&lt;code&gt;INITIAL, CALLABLE ... LIMIT&lt;/code&gt;, and repeatedly applies &lt;code&gt;CALLABLE&lt;/code&gt; first to the
initial value, and then to next value generated and so on, until it hits
&lt;code&gt;LIMIT&lt;/code&gt;. The limit here is &lt;code&gt;*&lt;/code&gt;, a special term called &lt;em&gt;Whatever&lt;/em&gt;, which in
this means it's unlimited. So the sequence operator returns a lazy,
potentially infinite list, and the tailing &lt;code&gt;.head(6)&lt;/code&gt; call limits it to 6
values.&lt;/p&gt;

&lt;p&gt;To find the most appropriate unit to print the size in, we have to iterate
over both the values and in the indexes of the array, which &lt;code&gt;for @steps.kv -&amp;gt;
$idx, $step { .. }&lt;/code&gt; accomplishes. &lt;code&gt;sprintf&lt;/code&gt;, known from other programming
languages, does the actual formatting to one digit after the dot, and appends
the unit.&lt;/p&gt;

&lt;h2&gt;Generating a Tree Map&lt;/h2&gt;

&lt;p&gt;One possible visualization of file and directory sizes is a &lt;em&gt;tree map&lt;/em&gt;, which
represents each directory as a rectangle, and a each file inside it as a
rectangle inside directory's rectangle. The size of each rectangle is
proportional to the size of the file or directory it represents.&lt;/p&gt;

&lt;p&gt;We'll generate an SVG file containing all those rectangles. Modern browsers
support displaying those files, and also show mouse-over texts for each
rectangle. This alleviates the burden to actually label the rectangnles, which
can be quite a hassle.&lt;/p&gt;

&lt;p&gt;To generate the SVG, we'll use the &lt;code&gt;SVG&lt;/code&gt; module, which you can install with&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ zef install SVG
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ panda install SVG
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;depending on the module installer you have available.&lt;/p&gt;

&lt;p&gt;This module provides a single static method, to which you pass
nested pairs. Pairs whose values are arrays are turned into XML tags, and
other pairs are turned into attributes. For example this Perl 6 script&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;use SVG;
print SVG.serialize(
    :svg[
        width =&amp;gt; 100,
        height =&amp;gt; 20,
        title =&amp;gt; [
            'example',
        ]
    ],
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;produces this output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot;
     xmlns:svg=&quot;http://www.w3.org/2000/svg&quot;
     xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;
     width=&quot;100&quot;
     height=&quot;20&quot;&amp;gt;
        &amp;lt;title&amp;gt;example&amp;lt;/title&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(without the indention). The &lt;code&gt;xmlns&lt;/code&gt;-tags are helpfully added by the &lt;code&gt;SVG&lt;/code&gt;
module, and are necessary for programs to recognize the file as SVG.&lt;/p&gt;

&lt;p&gt;To return to the tree maps, a very simple way to lay out the rectangle is to
recurse into areas, and for each area subdivide it either horizontally or
vertically, depending on which axis is longer:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub tree-map($tree, :$x1!, :$x2!, :$y1!, :$y2) {
    # do not produce rectangles for small files/dirs
    return if ($x2 - $x1) * ($y2 - $y1) &amp;lt; 20;

    # produce a rectangle for the current file or dir
    take 'rect' =&amp;gt; [
        x      =&amp;gt; $x1,
        y      =&amp;gt; $y1,
        width  =&amp;gt; $x2 - $x1,
        height =&amp;gt; $y2 - $y1,
        style  =&amp;gt; &quot;fill:&quot; ~ random-color(),
        title  =&amp;gt; [$tree.name],
    ];
    return if $tree ~~ File;

    if $x2 - $x1 &amp;gt; $y2 - $y1 {
        # split along the x axis
        my $base = ($x2 - $x1) / $tree.total-size;
        my $new-x = $x1;
        for $tree.children -&amp;gt; $child {
            my $increment = $base * $child.total-size;
            tree-map(
                $child,
                x1 =&amp;gt; $new-x,
                x2 =&amp;gt; $new-x + $increment,
                :$y1,
                :$y2,
            );
            $new-x += $increment;
        }
    }
    else {
        # split along the y axis
        my $base = ($y2 - $y1) / $tree.total-size;
        my $new-y = $y1;
        for $tree.children -&amp;gt; $child {
            my $increment = $base * $child.total-size;
            tree-map(
                $child,
                :$x1,
                :$x2,
                y1 =&amp;gt; $new-y,
                y2 =&amp;gt; $new-y + $increment,
            );
            $new-y += $increment;
        }
    }
}

sub random-color {
    return 'rgb(' ~ (1..3).map({ (^256).pick }).join(',') ~ ')';
}

sub MAIN($dir = '.', :$type=&quot;flame&quot;) {
    my $tree = tree($dir.IO);
    use SVG;
    my $width = 1024;
    my $height = 768;
    say SVG.serialize(
        :svg[
            :$width,
            :$height,
            | gather tree-map $tree, x1 =&amp;gt; 0, x2 =&amp;gt; $width, y1 =&amp;gt; 0, y2 =&amp;gt; $height
        ]
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src=&quot;https://perlgeek.de/images/blog/perl-6/box-hover.png&quot;&gt;&lt;br /&gt;
Tree map of an example directory, with random colors and a mouse-over hover identifying one of the files.&lt;/p&gt;

&lt;p&gt;The generated file is not pretty, due to the random colors, and due to some
files being identified as very narrow rectangles. But it does make it obvious
that there are a few big files, and many mostly small files in a directory
(which happens to be the &lt;code&gt;.git&lt;/code&gt; directory of a repository). Viewing a file in
a browser shows the name of the file on mouse over.&lt;/p&gt;

&lt;p&gt;How did we generate this file?&lt;/p&gt;

&lt;p&gt;Sub &lt;code&gt;tree-map&lt;/code&gt; calls &lt;code&gt;take&lt;/code&gt; to adds elements to a result list, so it must be
called in the context of a &lt;code&gt;gather&lt;/code&gt; statement. &lt;code&gt;gather { take 1; take 2 }&lt;/code&gt;
returns a lazy list of two elements, &lt;code&gt;1, 2&lt;/code&gt;. But the &lt;code&gt;take&lt;/code&gt; calls don't have
to occur in the lexical scope of the &lt;code&gt;gather&lt;/code&gt;, they can be in any code
that's directly or indirectly called from the &lt;code&gt;gather&lt;/code&gt;. We call that the
&lt;em&gt;dynamic scope&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The rest of sub &lt;code&gt;tree-map&lt;/code&gt; is mostly straight-forward. For each direction in
which the remaining rectangle can be split, we calculate a base unit that
signifies how many pixels a byte should take up. This is used to split up the
current canvas into smaller ones, and use those to recurse into &lt;code&gt;tree-map&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The random color generation uses &lt;code&gt;^256&lt;/code&gt; to create a range from 0 to 256
(exclusive), and &lt;code&gt;.pick&lt;/code&gt; returns a random element from this range. The result
is a random CSS color string like &lt;code&gt;rgb(120,240,5)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In sub MAIN, the &lt;code&gt;gather&lt;/code&gt; returns a list, which would normally be
nested inside the outer array. The pipe symbol &lt;code&gt;|&lt;/code&gt; in &lt;code&gt;:svg[ ..., | gather
... ]&lt;/code&gt; before the gather prevents the normal nesting, and flattens the list
into the outer array.&lt;/p&gt;

&lt;h2&gt;Flame Graphs&lt;/h2&gt;

&lt;p&gt;The disadvantage of tree maps as generated before is that the human brain
isn't very good at comparing rectangle sizes of different aspect ratios, so if
their ratio of width to height is very different. Flame graphs prevent this
perception errors by showing file sizes as horizontal bars. The vertical
arrangement indicates the nesting of directories and files inside other
directories. The disadvantage is that less of the available space is used for
visualizing the file sizes.&lt;/p&gt;

&lt;p&gt;Generating flame graphs is easier than tree maps, because you only need to
subdivide in one direction, whereas the height of each bar is fixed, here to
15 pixel:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub flame-graph($tree, :$x1!, :$x2!, :$y!, :$height!) {
    return if $y &amp;gt;= $height;
    take 'rect' =&amp;gt; [
        x      =&amp;gt; $x1,
        y      =&amp;gt; $y,
        width  =&amp;gt; $x2 - $x1,
        height =&amp;gt; 15,
        style  =&amp;gt; &quot;fill:&quot; ~ random-color(),
        title  =&amp;gt; [$tree.name ~ ', ' ~ format-size($tree.total-size)],
    ];
    return if $tree ~~ File;

    my $base = ($x2 - $x1) / $tree.total-size;
    my $new-x = $x1;

    for $tree.children -&amp;gt; $child {
        my $increment = $base * $child.total-size;
        flame-graph(
            $child,
            x1 =&amp;gt; $new-x,
            x2 =&amp;gt; $new-x + $increment,
            y =&amp;gt; $y + 15,
            :$height,
        );
        $new-x += $increment;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can add a switch to sub &lt;code&gt;MAIN&lt;/code&gt; to call either &lt;code&gt;tree-map&lt;/code&gt; or &lt;code&gt;flame-graph&lt;/code&gt;,
depending on a command line option:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sub MAIN($dir = '.', :$type=&quot;flame&quot;) {
    my $tree = tree($dir.IO);
    use SVG;
    my $width = 1024;
    my $height = 768;
    my &amp;amp;grapher = $type eq 'flame'
            ?? { flame-graph $tree, x1 =&amp;gt; 0, x2 =&amp;gt; $width, y =&amp;gt; 0, :$height }
            !! { tree-map    $tree, x1 =&amp;gt; 0, x2 =&amp;gt; $width, y1 =&amp;gt; 0, y2 =&amp;gt; $height }
    say SVG.serialize(
        :svg[
            :$width,
            :$height,
            | gather grapher()
        ]
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since SVG's coordinate system places the zero of the vertical axis at the top,
this actually produces an inverted flame graph, sometimes called icicle graph:&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;https://perlgeek.de/images/blog/perl-6/flame-hover.png&quot;&gt;&lt;br /&gt;
Inverted flame graph with random colors, where the width of each bar
represents a file/directory size, and the vertical position the nesting inside
a directory.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;We've explored tree maps and flame graphs to visualize which files and
directories use up how much disk space.&lt;/p&gt;

&lt;p&gt;But the code contains quite some duplications. Next week we'll explore
techniques from functional programming to reduce code duplication. We'll also
try to make the resulting files a bit prettier.&lt;/p&gt;

&lt;div id=&quot;mc_embed_signup&quot;&gt;
&lt;form action=&quot;//perlgeek.us12.list-manage.com/subscribe/post?u=ea4954d15b6283987b9d1b161&amp;amp;id=207c668582&quot; method=&quot;post&quot; id=&quot;mc-embedded-subscribe-form&quot; name=&quot;mc-embedded-subscribe-form&quot; class=&quot;validate&quot; target=&quot;_blank&quot; novalidate&gt;
    &lt;div id=&quot;mc_embed_signup_scroll&quot;&gt;
	&lt;h2&gt;Subscribe to the Perl 6 book mailing list&lt;/h2&gt;
&lt;div class=&quot;indicates-required&quot;&gt;&lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt; indicates required&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-EMAIL&quot;&gt;Email Address  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;email&quot; value=&quot;&quot; name=&quot;EMAIL&quot; class=&quot;required email&quot; id=&quot;mce-EMAIL&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;mc-field-group&quot;&gt;
	&lt;label for=&quot;mce-FNAME&quot;&gt;First Name  &lt;span class=&quot;asterisk&quot;&gt;*&lt;/span&gt;
&lt;/label&gt;
	&lt;input type=&quot;text&quot; value=&quot;&quot; name=&quot;FNAME&quot; class=&quot;required&quot; id=&quot;mce-FNAME&quot;&gt;
&lt;/div&gt;
	&lt;div id=&quot;mce-responses&quot; class=&quot;clear&quot;&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-error-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
		&lt;div class=&quot;response&quot; id=&quot;mce-success-response&quot; style=&quot;display:none&quot;&gt;&lt;/div&gt;
	&lt;/div&gt;    &lt;!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups--&gt;
    &lt;div style=&quot;position: absolute; left: -5000px;&quot; aria-hidden=&quot;true&quot;&gt;&lt;input type=&quot;text&quot; name=&quot;b_ea4954d15b6283987b9d1b161_207c668582&quot; tabindex=&quot;-1&quot; value=&quot;&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;clear&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;Subscribe&quot; name=&quot;subscribe&quot; id=&quot;mc-embedded-subscribe&quot; class=&quot;button&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'&gt;&lt;/script&gt;&lt;script type='text/javascript'&gt;(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';fnames[1]='FNAME';ftypes[1]='text';}(jQuery));var $mcj = jQuery.noConflict(true);&lt;/script&gt;
&lt;!--End mc_embed_signup--&gt;



</description>
  </item>
 
</channel></rss>