summaryrefslogtreecommitdiff
path: root/content/posts/2018
diff options
context:
space:
mode:
Diffstat (limited to 'content/posts/2018')
-rw-r--r--content/posts/2018/2018-02-05-why-perl6.md274
-rw-r--r--content/posts/2018/2018-03-20-perl6-introduction-to-application-programming.md774
-rw-r--r--content/posts/2018/2018-05-07-sparrowdo-getting-started.md235
-rw-r--r--content/posts/2018/2018-08-15-the-perl-conference-in-glasgow.md304
-rw-r--r--content/posts/2018/2018-09-04-setting-up-pgp-with-a-yubikey.md443
-rw-r--r--content/posts/2018/2018-09-13-hackerrank-solutions-python3-and-perl6-part-1.md445
6 files changed, 2475 insertions, 0 deletions
diff --git a/content/posts/2018/2018-02-05-why-perl6.md b/content/posts/2018/2018-02-05-why-perl6.md
new file mode 100644
index 0000000..4be3965
--- /dev/null
+++ b/content/posts/2018/2018-02-05-why-perl6.md
@@ -0,0 +1,274 @@
+---
+title: Why Perl 6?
+date: 2018-02-05
+tags:
+- Perl6
+- Raku
+---
+
+# Why Perl 6?
+
+For about a year now, I've been working in Perl 6. Telling this to other people
+often brings about some confused faces. I've grown quite fond of Perl 6 the
+more I learn about it, yet the general developer community still seems to think
+Perl is a dirty word. In this article, I will detail some of the features that
+make me like Perl 6, and why I try to use it wherever possible.
+
+== Hassle-free command line arguments
+Whet creating an application, you usually want to be able to specify some
+arguments at runtime. Most times this happens using command line arguments or
+options. Perl 6 allows you to specify these in the
+[https://docs.perl6.org/language/functions#index-entry-MAIN](`MAIN`) subroutine
+signature.
+
+For instance, if I want the application to accept two string arguments, I can
+do it as easy as this:
+
+```raku
+sub MAIN (
+ Str $arg-one,
+ Str $arg-two,
+) {
+ ...
+}
+```
+
+Now, if you wanted to add an option like `--output=/path/to/file`, you can do
+it just like this:
+
+```raku
+sub MAIN (
+ Str $arg-one,
+ Str $arg-two,
+ Str :$output,
+) {
+ ...
+}
+```
+
+By default, if there's a `MAIN` available in your Perl 6 program, but the
+arguments or options supplied by the user are incorrect, it will display the
+right way to invoke the command, called the
+[https://docs.perl6.org/language/functions#index-entry-USAGE](`USAGE`).
+Ofcourse, this message can be changed if you wish, but the default is quite good
+for most use-cases.
+
+However, sometimes you want to add a little explanation to what the argument or
+option is intended for. Just for a liitle bit of additional user friendliness.
+
+Fear not, for this is also already covered by the defaults. In Perl, there was
+POD to document your code. In Perl 6, we have
+[https://docs.perl6.org/language/glossary#index-entry-POD](POD) as well. And
+these comments can be inspected at runtime to provide the user some
+information. And that's exactly what the default `USAGE` also does. So if you
+want to add some helpful comments to the arguments or the program itself,
+simply add the comments where you want them:
+
+```raku
+#| This is a sample program, just to showcase the awesome stuff available in
+#| Perl 6.
+sub MAIN (
+ Str $arg-one, #= Just a random argument
+ Str $arg-two, #= Yet another argument used for showcasing
+ Str :$output, #= Last but not least, an option which allows for a value
+) {
+ ...
+}
+```
+
+## Unicode
+
+What if you could support all languages with a single implementation? That's
+where unicode comes in. And Perl 6 currently has the best support for Unicode
+out of all programming languages available. Its only real competitor seems to
+be Swift (at the time of writing this).
+
+But not just for handling strings, Perl 6 uses unicode as a core language
+feature. This means you can use them in your source code as well. And that
+opens up some nice possibilities. Using the right unicode characters allows you
+to write cleaner and more concise code, reducing the cognitive load while
+trying to understand the program.
+
+For instance, if you're trying to do any kind of math, you can just use the
+π character as a regular character. Or use the ² to get the square of a certain
+number. This little piece is completely valid in Perl 6:
+
+```raku
+my $a = $r² ÷ π;
+```
+
+Now, if you're thinking "that looks neat, but how am I ever going to write
+these?", do not worry. Most operating systems and many editors have tools to let
+you input these. For instance, using `vim` with
+[https://github.com/vim-perl/vim-perl6](`vim-perl6`), you can just write "pi"
+and hit space (or type any non-alphabetical character).
+
+But not everyone is using an OS or an editor that makes it easy. And for those
+people, Perl 6 simply supports using
+[https://docs.perl6.org/language/unicode_ascii](ascii based operators). The
+previous block could also be written as follows:
+
+```raku
+my $a = $r ^ 2 / pi;
+```
+
+As unicode becomes more accepted, input methods will hopefully improve to make
+input easier for everyone in the long run. Those who can already input it
+easily don't have to wait for this future, Perl 6 already supports it.
+
+## Multithreading
+
+Multi-core processors are virtually everywhere these days. Yet many programming
+languages still don't support multithreaded application development natively,
+if at all. In Perl 6, running something in a different thread is as easy as
+wrapping it in a [https://docs.perl6.org/routine/start](`start`) block:
+
+```raku
+start {
+ do-something();
+}
+```
+
+`start` returns a [https://docs.perl6.org/type/Promise](`Promise`), which you can
+store in a scalar variable just like any other object. You can check on whether
+the `Promise` has completed already and check whether it died, for instance.
+
+Other aspects which can often be spread over multiple threads are loops or
+maps. For instance, consider the following
+[https://docs.perl6.org/routine/map](map) function:
+
+```raku
+@cats.map: {
+ $^cat.pat;
+}
+```
+
+This will pat each cat in turn, in the order they appear in the list. But you
+can speed up the patting process by patting multiple cats at the same time. And
+to get there, all you need to do is add a
+[https://docs.perl6.org/routine/race](`race`):
+
+```raku
+@cats.race.map: {
+ $^cat.pat;
+}
+```
+
+This will attempt to pat the cats over multiple threads, speeding up the
+process to pat all the cats. If the result of the pattings needs to be in the
+same order as the patting order, you use
+[https://docs.perl6.org/routine/hyper](`hyper`) instead of `race`:
+
+```raku
+@cats.hyper.map: {
+ $^cat.pat;
+}
+```
+
+## Object orientation
+
+Object oriented programming seems to be getting out of fashion with the new
+generation of developers. But it's still in wide use, being taught at most
+universities, and is often easy to explain to new developers as well.
+
+And Perl 6 has [https://docs.perl6.org/language/classtut#index-entry-OOP](OO)
+support built into its core:
+
+```raku
+class Foo
+{
+ has Str $some-field;
+
+ method bar (
+ Str $some-arg,
+ ) {
+ ...
+ }
+}
+```
+
+You can also have
+[https://docs.perl6.org/language/glossary#index-entry-Multi-Dispatch](multi-dispatch)
+methods on your classes, which are methods with the same names, but accepting
+different arguments or argument types. For instance:
+
+```raku
+class Foo
+{
+ multi method bar (
+ Str $some-arg,
+ ) {
+ ...
+ }
+
+ multi method bar (
+ Int $some-arg,
+ ) {
+ ...
+ }
+}
+```
+
+Which method is being used will be decided by the type of argument is being
+passed in, in this case either a [https://docs.perl6.org/type/Str](`Str`) or an
+[https://docs.perl6.org/type/Int](`Int`).
+
+## Functional programming
+
+Whilst OO is considered being old more and more, functional programming is
+gaining ground. And this paradigm is fully supported in the core of Perl 6 as
+well. You've seen the `map` example already while patting cats earlier, for
+instance.
+
+But there's much more on the functional playing field, such as the
+[https://docs.perl6.org/routine/==%3E](`==>`) operator, known as the
+[https://docs.perl6.org/language/operators#infix_==%3E](feed operator). It
+simply passed the output of a statement as the last argument to the next
+statement:
+
+```raku
+@grumpy-cats
+ ==> feed()
+ ==> pat()
+ ==> snuggle()
+ ==> my @happy-cats;
+```
+
+This will take the `@grumpy-cats`, feed them, pat them, snuggle them and put
+the result into `@happy-cats`. You could've chained the calls using a `.`
+instead, and Perl 6 allows you to do this too. But the `==>` looks much more
+readable to me, which is why I prefer using this instead.
+
+I'm still exploring the functional programming field myself, but these few
+things have made me happy exploring it.
+
+## Community
+
+(Almost) last, but certainly not least, the Perl 6 community is amazing. It's
+been the friendliest bunch I've been with, both on IRC, their mailing lists and
+in real life. Everyone is welcoming, and they try to help you whenever they
+can.
+
+Community is important to help you out whenever you get stuck for whatever
+reason. A friendly community is the best you can get here to keep you a happy
+developer yourself as well.
+
+## Other little aspects
+
+There's a few neat things I can do in Perl 6 that I can't do in (most) other
+languages, but aren't important enough to warrant a large section to show them
+off.
+
+### Dashes in names
+
+You can use dashes in names: Things like `my $foo-bar` is valid, just like
+`method foo-bar`. It's nothing big on itself, but I've found it makes reading
+code much more enjoyable than pascalCase, CamelCase or snake_case.
+
+### Gradual typing
+
+You don't *need* to use types in Perl 6. But when you want to use them (for
+making use of multi-dispatch, for example), you can just start using them. If
+types are added, the compiler will make sure the types are correct. If not, you
+can always do them yourself (but why would you, when the compiler can do a
+better job for free).
diff --git a/content/posts/2018/2018-03-20-perl6-introduction-to-application-programming.md b/content/posts/2018/2018-03-20-perl6-introduction-to-application-programming.md
new file mode 100644
index 0000000..30912c9
--- /dev/null
+++ b/content/posts/2018/2018-03-20-perl6-introduction-to-application-programming.md
@@ -0,0 +1,774 @@
+---
+title: "Perl 6 - Introduction to application programming"
+date: 2018-03-20
+tags:
+- Tutorial
+- Perl6
+- Assixt
+- GTK
+- Programming
+- Raku
+---
+
+# Perl 6 - Introduction to application programming
+
+In this tutorial, I'll be guiding you through creating a simple application in
+Perl 6. If you don't have Perl 6 installed yet, get the
+[http://rakudo.org/how-to-get-rakudo/](Rakudo Star) distribution for your OS.
+Alternatively, you can use the [https://hub.docker.com/_/rakudo-star/](Docker
+image).
+
+The application itself will be a simple dice-roller. You give it a number of
+dice to roll, and the number of sides the die has. We'll start off by creating
+it as a console application, then work to make it a GUI as well with the
+`GTK::Simple` module.
+
+## Preparation
+
+First, you'll want to install the libgtk headers. How to get these depends on
+your distro of choice. For Debian-based systems, which includes Ubuntu and
+derivatives, this command would be the following `apt` invocation:
+
+```txt
+$ apt install libgtk-3-dev
+```
+
+For other distros, please consult your documentation.
+
+To ease up module/application building, I'll use `App::Assixt`. This module
+eases up on common tasks required for building other modules or applications.
+So we'll start by installing this module through `zef`.
+
+```txt
+$ zef install App::Assixt
+```
+
+{< admonition title="note" >}
+You may need to rehash your `$PATH` as well, which can be done using `hash -r`
+on `bash`, or `rehash` for `zsh`. For other shells, consult your manual.
+{< / admonition >}
+
+Next up, we can use `assixt` to create the new skeleton of our application,
+with the `new` subcommand. This will ask for some user input, which will be
+recorded in the `META6.json`, a json-formatted file to keep track of meta
+information about the module. `assixt` should take care of this file for you,
+so you never need to actually deal with it.
+
+```txt
+$ assixt new
+```
+
+### assixt input
+
+Since the `assixt new` command requires some input, I'll walk through these
+options and explain how these would affect your eventual application.
+
+#### Name of the module
+
+This is the name given to the module. This will be used for the directory name,
+which by default in `assixt` will be `perl6-` prepended to a lower-case version
+of the module name. If you ever wish to make a module that is to be shared in
+the Perl 6 ecosystem, this should be unique across the entire ecosystem. If
+you're interested in some guidelines, the
+[https://pause.perl.org/pause/query?ACTION=pause_namingmodules](PAUSE
+guidelines) seem to apply pretty well to Perl 6 as well.
+
+For this application, we'll use `Local::App::Dicer`, but you can use whatever
+name you'd prefer here.
+
+#### Your name
+
+Your name. This will be used as the author's name in the `META6.json`. It is
+used to find out who made it, in order to report issues (or words of praise,
+of course).
+
+#### Your email address
+
+Your email address. Like your name, it will be used in case someone has to
+contact you in regards off the module.
+
+#### Perl 6 version
+
+This defaults to `c` right now, and you can just hit enter to accept it. In the
+future, there will be a Perl 6.d available as well, in which case you can use
+this to indicate you want to use the newer features introduced in 6.d. This is
+not the case yet, so you just want to go with the default `c` value here.
+
+#### Module description
+
+A short description of your module, preferably a single sentence. This is
+useful to people wondering what the module is for, and module managers can show
+to the user.
+
+#### License key
+
+This indicates the license under which your module is distributed. This
+defaults to `GPL-3.0`, which I strongly recommend to use. The de-facto
+default seems to be `Artistic-2.0`, which is also used for Perl 6 itself.
+
+This identifier is based on the [https://spdx.org/licenses/](SPDX license list).
+Anything not mentioned in this list is not acceptable. #TODO Clarify why
+
+## Writing your first test
+
+With the creation of the directory structure and metadata being taken care of
+by `assixt`, we can now start on writing things. Tests are not mandatory, but
+are a great tool for quickly checking if everything works. If you make larger
+applications, it really helps not having to manually test anything. Another
+benefit is that you can quickly see if your changes, or those of someone else,
+break anything.
+
+Creating the base template for tests, `assixt` can help you out again: `assixt
+touch` can create templates in the right location, so you don't have to deal
+with it. In this case we want to create a test, which we'll call "basic".
+
+```txt
+$ assixt touch test basic
+```
+
+This will create the file `t/basic.t` in your module directory. Its contents
+will look as follows:
+
+```raku
+#! /usr/bin/env perl6
+
+use v6.c;
+
+use Test;
+
+ok True;
+
+done-testing;
+
+# vim: ft=perl6
+```
+
+The only test it has right now is `ok True`, which will always pass testing. We
+will change that line into something more usable for this application:
+
+```raku
+use Local::App::Dicer;
+
+plan 2;
+
+subtest "Legal rolls", {
+ plan 50;
+
+ for 1..50 {
+ ok 1 ≤ roll($_) ≤ $_, "Rolls between 1 and $_";
+ }
+}
+
+subtest "Illegal rolls", {
+ plan 3;
+
+ throws-like { roll(0) }, X::TypeCheck::Binding::Parameter, "Zero is not accepted";
+ throws-like { roll(-1) }, X::TypeCheck::Binding::Parameter, "Negative rolls are not accepted";
+ throws-like { roll(1.5) }, X::TypeCheck::Binding::Parameter, "Can't roll half sides";
+}
+```
+
+{< admonition title="note" >}
+Perl 6 allows mathematical characters to make your code more concise, as with
+the ≤ in the above block. If you use http://www.vim.org/[vim], you can make use
+of the https://github.com/vim-perl/vim-perl6[vim-perl6] plugin, which has an
+option to change the longer, ascii-based ops (in this case `\<=`) into the
+shorter unicode based ops (in this case `≤`). This specific feature requires
+`let g:perl6_unicode_abbrevs = 1` in your `vimrc` to be enabled with
+`vim-perl6`.
+
+If that's not an option, you can use a
+https://en.wikipedia.org/wiki/Compose_key[compose key]. If that is not viable
+either, you can also stick to using the ascii-based ops. Perl 6 supports both
+of them.
+{< / admonition >}
+
+This will run 53 tests, split up in two
+[https://docs.perl6.org/language/testing#Grouping_tests](subtests). Subtests are
+used to logically group your tests. In this case, the calls that are correct
+are in one subtest, the calls that should be rejected are in another.
+
+The `plan` keywords indicate how many tests should be run. This will help spot
+errors in case your expectations were not matched. For more information on
+testing, check out [https://docs.perl6.org/language/testing](the Perl 6 docs on
+testing).
+
+We're making use of two test routines, `ok` and `throws-like`. `ok` is a
+simple test: if the given statement is truthy, the test succeeds. The other
+one, `throws-like`, might require some more explanation. The first argument it
+expects is a code block, hence the `{ }`. Inside this block, you can run any
+code you want. In this case, we run code that we know shouldn't work. The
+second argument is the exception it should throw. The test succeeds if the
+right exception is thrown. Both `ok` and `throws-like` accept a descriptive
+string as optional last argument.
+
+### Running the tests
+
+A test is useless if you can't easily run it. For this, the `prove` utility
+exists. You can use `assixt test` to run these tests properly as well, saving
+you from having to manually type out the full `prove` command with options.
+
+```txt
+$ assixt test
+```
+
+You might notice the tests are currently failing, which is correct. The
+`Local::App::Dicer` module doesn't exist yet to test against. We'll be working
+on that next.
+
+{< admonition title="note" >}
+For those interested, the command run by `assixt test` is `prove -e "perl6
+-Ilib" t`. This will include the `lib` directory into the `PERL6PATH` to be
+able to access the libraries we'll be making. The `t` argument specifies the
+directory containing the tests.
+{< / admonition >}
+
+## Creating the library
+
+Again, let's start with a `assixt` command to create the base template. This
+time, instead of `touch test`, we'll use `touch lib`.
+
+```txt
+$ assixt touch unit Local::App::Dicer
+```
+
+This will generate a template file at `lib/Local/App/Dicer.pm6` which some
+defaults set. The file will look like this.
+
+```raku
+#! /usr/bin/env false
+
+use v6.c;
+
+unit module Local::App::Dicer;
+```
+
+The first line is a [https://en.wikipedia.org/wiki/Shebang_(Unix)](shebang). It
+informs the shell what to do when you try to run the file as an executable
+program. In this case, it will run `false`, which immediately exits with a
+non-success code. This file needs to be run as a Perl 6 module file, and
+running it as a standalone file is an error.
+
+The `use v6.c` line indicates what version of Perl 6 should be used, and is
+taken from the `META6.json`, which was generated with `assixt new`. The last
+line informs the name of this module, which is `Local::App::Dicer`. Beneath
+this, we can add subroutines, which can be exported. These can then be accessed
+from other Perl 6 files that `use` this module.
+
+### Creating the `roll` subroutine
+
+Since we want to be able to `roll` a die, we'll create a subroutine to do
+exactly that. Let's start with the signature, which tells the compiler the name
+of the subroutine, which arguments it accepts, their types and what type the
+subroutine will return.
+
+{< admonition title="tip" >}
+Perl 6 is gradually typed, so all type information is optional. The subroutine
+arguments are optional too, but you will rarely want a subroutine that doesn't
+have an argument list.
+{< / admonition >}
+
+```raku
+sub roll($sides) is export
+{
+ $sides
+}
+```
+
+Let's break this down.
+
+- `sub` informs the compiler we're going to create a subroutine.
+- `roll` is the name of the subroutine we're going to create.
+- `$sides` defines an argument used by the subroutine.
+- `is export` tells the compiler that this subroutine is to be exported. This
+ allows access to the subroutine to another program that imports this module
+ through a `use`.
+- `{ $sides }` is the subroutine body. In Perl 6, the last statement is also
+ the return value in a code block, thus this returns the value of $sides. A
+ closing `;` is also not required for the last statement in a block.
+
+If you run `assixt test` now, you can see it only fails 1/2 subtests:
+
+```raku
+# TODO: Add output of failing tests
+```
+
+Something is going right, but not all of it yet. The 3 tests to check for
+illegal rolls are still failing, because there's no constraints on the input of
+the subroutine.
+
+### Adding constraints
+
+The first constraint we'll add is to limit the value of `$sides` to an `Int:D`.
+The first part of this constraint is common in many languages, the `Int` part.
+The `:D` requires the argument to be **defined**. This forces an actual
+existing instance of `Int`, not a `Nil` or undefined value.
+
+```raku
+sub roll(Int:D $sides) is export
+```
+
+Fractional input is no longer allowed, since an `Int` is always a round number.
+But an `Int` is still allowed to be 0 or negative, which isn't possible in a
+dice roll. Nearly every language will make you solve these two cases in the
+subroutine body. But in Perl 6, you can add another constraint in the signature
+that checks for exactly that:
+
+```raku
+sub roll(Int:D $sides where $sides > 0) is export
+```
+
+The `where` part specifies additional constraints, in this case `$sides > 0`.
+So now, only round numbers larger than 0 are allowed. If you run `assixt test`
+again, you should see all tests passing, indicating that all illegal rolls are
+now correctly disallowed.
+
+### Returning a random number
+
+So now that we can be sure that the input is always correct, we can start on
+making the output more random. In Perl 6, you can take a number and call
+`.rand` on it, to get a random number between 0 and the value of the number you
+called it on. This in turn can be rounded up to get a number ranging from 1 to
+the value of the number you called `.rand` on. These two method calls can also
+be changed to yield concise code:
+
+```raku
+sub roll(Int:D $sides where $sides > 0) is export
+{
+ $sides.rand.ceiling
+}
+```
+
+That's all we need from the library itself. Now we can start on making a usable
+program out of it.
+
+## Adding a console interface
+
+First off, a console interface. `assixt` can `touch` a starting point for an
+executable script as well, using `assixt touch bin`:
+
+```txt
+$ assixt touch bin dicer
+```
+
+This will create the file `bin/dicer` in your repository, with the following
+template:
+
+```raku
+#! /usr/bin/env perl6
+
+use v6.c;
+
+sub MAIN
+{
+ …
+}
+```
+
+The program will run the `MAIN` sub by default. We want to slightly change this
+`MAIN` signature though, since we want to accept user input. And it just so
+happens that you can specify the command line parameters in the `MAIN`
+signature in Perl 6. This lets us add constraints to the parameters and give
+them better names with next to no effort. We want to accept two numbers, one
+for the number of dice, and one for the number of sides per die:
+
+```raku
+sub MAIN(Int:D $dice, Int:D $sides where { $dice > 0 && $sides > 0 })
+```
+
+Here we see the `where` applying constraints again. If you try running this
+program in its current state, you'll have to run the following:
+
+```txt
+$ perl6 -Ilib bin/dicer
+Usage:
+ bin/dicer <dice> <sides>
+```
+
+This will return a list of all possible ways to invoke the program. There's one
+slight problem right now. The usage description does not inform the user that
+both arguments need to be larger than 0. We'll take care of that in a moment.
+First we'll make this part work the way we want.
+
+To do that, let's add a `use` statement to our `lib` directory, and call the
+`roll` function we created earlier. The `bin/dicer` file will come to look as
+follows:
+
+```raku
+#! /usr/bin/env perl6
+
+use v6.c;
+
+use Local::App::Dicer;
+
+sub MAIN(Int:D $dice, Int:D $sides where { $dice > 0 && $sides > 0 })
+{
+ say $dice × roll($sides)
+}
+```
+
+{< admonition title="note" >}
+Just like the `≤` character, Perl 6 allows to use the proper multiplication
+character `×` (this is not the letter `x`!). You can use the more widely known
+`*` for multiplication as well.
+{< / admonition >}
+
+If you run the program with the arguments `2` and `20` now, you'll get a random
+number between 2 and 40, just like we expect:
+
+```txt
+$ perl6 -Ilib bin/dicer 2 20
+18
+```
+
+### The usage output
+
+Now, we still have the trouble of illegal number input not clearly telling
+what's wrong. We can do a neat trick with
+[https://docs.perl6.org/language/functions#index-entry-USAGE](the USAGE sub) to
+achieve this. Perl 6 allows a subroutine with the name `USAGE` to be defined,
+overriding the default behaviour.
+
+Using this, we can generate a friendlier message informing the user what they
+need to supply more clearly. The `USAGE` sub would look like this:
+
+```raku
+sub USAGE
+{
+ say "Dicer requires two positive, round numbers as arguments."
+}
+```
+
+If you run the program with incorrect parameters now, it will show the text
+from the `USAGE` subroutine. If the parameters are correct, it will run the
+`MAIN` subroutine.
+
+You now have a working console application in Perl 6!
+
+## a simple GUI
+
+But that's not all. Perl 6 has a module to create GUIs with the
+[https://www.gtk.org/](GTK library) as well. For this, we'll use the
+[https://github.com/perl6/gtk-simple](`GTK::Simple`) module.
+
+You can add this module as a dependency to the `Local::App::Dicer` repository
+with `assixt` as well, using the `depend` command. By default, this will also
+install the dependency locally so you can use it immediately.
+
+```txt
+$ assixt depend GTK::Simple
+```
+
+### Multi subs
+
+Next, we could create another executable file and call it `dicer-gtk`. However,
+I can also use this moment to introduce
+[https://docs.perl6.org/language/glossary#index-entry-multi-method](multi
+methods). These are subs with the same name, but differing signatures. If a
+call to such a sub could potentially match multiple signatures, the most
+specific one will be used. We will add another `MAIN` sub, which will be called
+when `bin/dicer` is called with the `--gtk` parameter.
+
+We should also update the `USAGE` sub accordingly, of course. And while we're
+at it, let's also include the `GTK::Simple` and `GTK::Simple::App` modules. The
+first pulls in all the different GTK elements we will use later on, while the
+latter pulls in the class for the base GTK application window. The updated
+`MAIN`, `USAGE` and `use` parts will now look like this:
+
+```raku
+use Local::App::Dicer;
+use GTK::Simple;
+use GTK::Simple::App;
+
+multi sub MAIN(Int:D $dice, Int:D $sides where { $dice > 0 && $sides > 0 })
+{
+ say $dice × roll($sides)
+}
+
+multi sub MAIN(Bool:D :$gtk where $gtk == True)
+{
+ # TODO: Create the GTK version
+}
+
+sub USAGE
+{
+ say "Launch Dicer as a GUI with --gtk, or supply two positive, round numbers as arguments.";
+}
+```
+
+There's a new thing in a signature header here as well, `:$gtk`. The `:` in
+front of it makes it a named argument, instead of a positional one. When used
+in a `MAIN`, this will allow it to be used like a long-opt, thus as `--gtk`.
+Its use in general subroutine signatures is explained in the next chapter.
+
+Running the application with `--gtk` gives no output now, because the body only
+contains a comment. Let's fix that.
+
+### Creating the window
+
+First off, we require a `GTK::Simple::App` instance. This is the main window,
+in which we'll be able to put elements such as buttons, labels, and input
+fields. We can create the `GTK::Simple::App` as follows:
+
+```raku
+my GTK::Simple::App $app .= new(title => "Dicer");
+```
+
+This one line brings in some new Perl 6 syntax, namely the `.=` operator.
+There's also the use of a named argument in a regular subroutine.
+
+The `.=` operator performs a method on the variable on the left. In our case,
+it will call the `new` subroutine, which creates a new instance of the
+`GTK::Simple::App` class. This is commonly referred to as the **constructor**.
+
+The named argument list (`title => "Dicer"`) is another commonly used feature
+in Perl 6. Any method can be given a non-positional, named parameter. This is
+done by appending a `:` in front of the variable name in the sub signature.
+This has already been used in our code, in `multi sub MAIN(Bool :$gtk where
+$gtk == True)`. This has a couple of benefits, which are explained in the
+[https://docs.perl6.org/type/Signature#index-entry-positional_argument_%28Signature%29_named_argument_%28Signature%29](Perl 6 docs on signatures).
+
+### Creating the elements
+
+Next up, we can create the elements we'd like to have visible in our
+application window. We needed two inputs for the console version, so we'll
+probably need two for the GUI version as well. Since we have two inputs, we
+want labels for them. The roll itself will be performed on a button press.
+Lastly, we will want another label to display the outcome. This brings us to 6
+elements in total:
+
+- 3 labels
+- 2 entries
+- 1 button
+
+```raku
+my GTK::Simple::Label $label-dice .= new(text => "Amount of dice");
+my GTK::Simple::Label $label-sides .= new(text => "Dice value");
+my GTK::Simple::Label $label-result .= new(text => "");
+my GTK::Simple::Entry $entry-dice .= new(text => 0);
+my GTK::Simple::Entry $entry-sides .= new(text => 0);
+my GTK::Simple::Button $button-roll .= new(label => "Roll!");
+```
+
+This creates all elements we want to show to the user.
+
+### Show the elements in the application window
+
+Now that we have our elements, let's put them into the application window.
+We'll need to put them into a layout as well. For this, we'll use a grid. The
+`GTK::Simple::Grid` constructor takes pairs, with the key being a tuple
+containing 4 elements, and the value containing the element you want to show.
+The tuple's elements are the `x`, `y`, `w` and `h`, which are the x
+coordinates, y coordinates, width and height respectively.
+
+This in turn takes us to the following statement:
+
+```raku
+$app.set-content(
+ GTK::Simple::Grid.new(
+ [0, 0, 1, 1] => $label-dice,
+ [1, 0, 1, 1] => $entry-dice,
+ [0, 1, 1, 1] => $label-sides,
+ [1, 1, 1, 1] => $entry-sides,
+ [0, 2, 2, 1] => $button-roll,
+ [0, 3, 2, 1] => $label-result,
+ )
+);
+```
+
+Put a `$app.run` beneath that, and try running `perl6 -Ilib bin/dicer --gtk`.
+That should provide you with a GTK window with all the elements visible in the
+position we want. To make it a little more appealing, we can add a
+`border-width` to the `$app`, which adds a margin between the border of the
+application window, and the grid inside the window.
+
+```raku
+$app.border-width = 20;
+$app.run;
+```
+
+You may notice that there's no `()` after the `run` method call. In Perl 6,
+these are optional if you're not supplying any arguments any way.
+
+### Binding an action to the button
+
+Now that we have a visible window, it's time to make the button perform an
+action. The action we want to execute is to take the values from the two
+inputs, roll the correct number of dice with the correct number of sides, and
+present it to the user.
+
+The base code for binding an action to a button is to call `.clicked.tap` on it,
+and provide it with a code block. This code will be executed whenever the
+button is clicked.
+
+```raku
+$button-roll.clicked.tap: {
+};
+```
+
+You see we can also invoke a method using `:`, and then supplying its
+arguments. This saves you the trouble of having to add additional `( )` around
+the call, and in this case it would be annoying to have to deal with yet
+another set of parens.
+
+Next, we give the code block something to actually perform:
+
+```raku
+$button-roll.clicked.tap: {
+ CATCH {
+ $label-result.text = "Can't roll with those numbers";
+ }
+
+ X::TypeCheck::Binding::Parameter.new.throw if $entry-dice.text.Int < 1;
+
+ $label-result.text = ($entry-dice.text.Int × roll($entry-sides.text.Int)).Str;
+};
+```
+
+There's some new things in this block of code, so let's go over these.
+
+- `CATCH` is the block in which we'll end up if an exception is thrown in this
+ scope. `roll` will throw an exception if the parameters are wrong, and this
+ allows us to cleanly deal with that.
+- `X::TypeCheck::Binding::Parameter.new.throw` throws a new exception of type
+ `X::TypeCheck::Binding::Parameter`. This is the same exception type as thrown
+ by `roll` if something is wrong. We need to check the number of dice manually
+ here, since `roll` doesn't take care of it, nor does any signature impose any
+ restrictions on the value of the entry box.
+- `if` behind another statement. This is something Perl 6 allows, and in some
+ circumstances can result in cleaner code. It's used here because it improves
+ the readability of the code, and to show that it's possible.
+
+## The completed product
+
+And with that, you should have a dice roller in Perl 6, with both a console and
+GTK interface. Below you can find the complete, finished sourcefiles which you
+should have by now.
+
+### t/basic.t
+
+```raku
+#! /usr/bin/env perl6
+
+use v6.c;
+
+use Test;
+use Local::App::Dicer;
+
+plan 2;
+
+subtest "Legal rolls", {
+ plan 50;
+
+ for 1..50 {
+ ok 1 ≤ roll($_) ≤ $_, "Rolls between 1 and $_";
+ }
+}
+
+subtest "Illegal rolls", {
+ plan 3;
+
+ throws-like { roll(0) }, X::TypeCheck::Binding::Parameter, "Zero is not accepted";
+ throws-like { roll(-1) }, X::TypeCheck::Binding::Parameter, "Negative rolls are not accepted";
+ throws-like { roll(1.5) }, X::TypeCheck::Binding::Parameter, "Can't roll half sides";
+}
+
+done-testing;
+
+# vim: ft=perl6
+```
+
+### lib/Local/App/Dicer.pm6
+
+```raku
+#! /usr/bin/env false
+
+use v6.c;
+
+unit module Local::App::Dicer;
+
+sub roll(Int:D $sides where $sides > 0) is export
+{
+ $sides.rand.ceiling;
+}
+```
+
+### bin/dicer
+
+```raku
+#! /usr/bin/env perl6
+
+use v6.c;
+
+use Local::App::Dicer;
+use GTK::Simple;
+use GTK::Simple::App;
+
+multi sub MAIN(Int:D $dice, Int:D $sides where { $dice > 0 && $sides > 0 })
+{
+ say $dice × roll($sides)
+}
+
+multi sub MAIN(Bool:D :$gtk where $gtk == True)
+{
+ my GTK::Simple::App $app .= new(title => "Dicer");
+ my GTK::Simple::Label $label-dice .= new(text => "Number of dice");
+ my GTK::Simple::Label $label-sides .= new(text => "Number of sides per die");
+ my GTK::Simple::Label $label-result .= new(text => "");
+ my GTK::Simple::Entry $entry-dice .= new(text => 0);
+ my GTK::Simple::Entry $entry-sides .= new(text => 0);
+ my GTK::Simple::Button $button-roll .= new(label => "Roll!");
+
+ $app.set-content(
+ GTK::Simple::Grid.new(
+ [0, 0, 1, 1] => $label-dice,
+ [1, 0, 1, 1] => $entry-dice,
+ [0, 1, 1, 1] => $label-sides,
+ [1, 1, 1, 1] => $entry-sides,
+ [0, 2, 2, 1] => $button-roll,
+ [0, 3, 2, 1] => $label-result,
+ )
+ );
+
+ $button-roll.clicked.tap: {
+ CATCH {
+ $label-result.text = "Can't roll with those numbers";
+ }
+
+ X::TypeCheck::Binding::Parameter.new.throw if $entry-dice.text.Int < 1;
+
+ $label-result.text = ($entry-dice.text.Int × roll($entry-sides.text.Int)).Str;
+ };
+
+ $app.border-width = 20;
+
+ $app.run;
+}
+
+sub USAGE
+{
+ say "Launch Dicer as a GUI with --gtk, or supply two positive, round numbers as arguments.";
+}
+```
+
+## Installing your module
+
+Now that you have a finished application, you probably want to install it as
+well, so you can run it by calling `dicer` in your shell. For this, we'll be
+using `zef`.
+
+To install a local module, tell `zef` to try and install the local directory
+you're in:
+
+```txt
+$ zef install .
+```
+
+This will resolve the dependencies of the local module, and then install it.
+You should now be able to run `dicer` from anywhere.
+
+{< admonition title="warning" >}
+With most shells, you have to "rehash" your `$PATH` as well. On `bash`, this is
+done with `hash -r`, on `zsh` it's `rehash`. If you're using any other shell,
+please consult the manual.
+{< / admonition >}
diff --git a/content/posts/2018/2018-05-07-sparrowdo-getting-started.md b/content/posts/2018/2018-05-07-sparrowdo-getting-started.md
new file mode 100644
index 0000000..b75de3a
--- /dev/null
+++ b/content/posts/2018/2018-05-07-sparrowdo-getting-started.md
@@ -0,0 +1,235 @@
+---
+title: Sparrowdo - Getting Started
+date: 2018-05-07
+tags:
+- LoneStar
+- Perl6
+- Raku
+- Sparrowdo
+- Tutorial
+---
+
+# Sparrowdo - Getting started
+
+[https://github.com/melezhik/sparrowdo](Sparrowdo) is a Perl 6 project to
+facilitate automatic configuration of systems. There's a
+[https://sparrowhub.org/](repository of useful modules) to make specific cases
+easier to work with, but the
+[https://github.com/melezhik/sparrowdo/blob/master/core-dsl.md](Core DSL) can
+already take care of many tasks. In this tutorial, I'll guide you through
+setting up Sparrowdo, bootstrapping it onto your local system, writing a task
+and running it.
+
+## Install Sparrowdo
+
+Sparrowdo is a [http://perl6.org/](Perl 6) project, so you'll need to have Perl
+6 installed. We'll also use the Perl 6 package manager
+[https://github.com/ugexe/zef/](zef) to install Sparrowdo itself. Luckily for
+us, there's a stable distribution of Perl 6 with everything we need added to it,
+called [https://rakudo.org/files](Rakudo Star). And to make it easier for
+GNU+Linux users, I wrote a tool to fetch the latest Rakudo Star release, compile
+it and install it, called [https://github.com/Tyil/lonestar](LoneStar). Since
+this tutorial will aim at GNU+Linux users, I'll use that to install Perl 6.
+
+### Installing Perl 6 with LoneStar
+
+LoneStar is a Bash application to download, compile and set up Perl 6. It's a
+standalone application, meaning you don't have to install it to your system. You
+can just run it from the source directory. First, we'll have to get the source
+directory, which we'll do using `git`.
+
+```txt
+mkdir -p ~/.local/src
+git clone https://github.com/tyil/lonestar.git ~/.local/src/lonestar
+cd !$
+```
+
+Now you have the LoneStar sources available in `~/.local/src/lonestar`. You can
+run the application using `./bin/lonestar`. Running it, you'll get some help
+output:
+
+```txt
+$ ./bin/lonestar
+lonestar - Installation manager for Rakudo Star
+
+Usage: lonestar <action> [arguments...]
+
+Actions:
+ help [action]
+ init [version=latest]
+ install [version=latest]
+ path [version=latest]
+ reinstall [version=latest]
+ upgrade
+```
+
+We'll be needing the `install` action to get Perl 6 installed, and the `init`
+action to configure the `$PATH` environment variable. Depending on your
+hardware, `install` may take a couple minutes as it will compile Rakudo Perl 6
+and install some base modules. You might want to grab a drink during this
+period.
+
+```txt
+$ ./bin/lonestar install
+$ eval $(./bin/lonestar init)
+$ perl6 -v
+This is Rakudo Star version 2018.04.1 built on MoarVM version 2018.04.1
+implementing Perl 6.c.
+```
+
+{< admonition title="note" >}
+If there's a newer version available of Rakudo Star, the version numbers given
+by `perl6 -v` will differ for you.
+{< / admonition >}
+
+### Installing Sparrowdo with zef
+
+Now that you have Perl 6 available and installed, you can continue on using
+`zef` to install Sparrowdo. `zef` is bundled with Rakudo Star, so you don't have
+to do anything to get it working.
+
+```txt
+zef install Sparrowdo
+```
+
+This will instruct `zef` to install Sparrowdo and all its dependencies. This can
+take a couple minutes, again depending on the hardware of your machine.
+
+## Bootstrapping your system
+
+The first step to working with Sparrowdo is bootstrapping the system you wish to
+use it with. In this case, that'll be the local system. There's a `--bootstrap`
+option to do this automatically.
+
+```txt
+sparrowdo --bootstrap
+```
+
+{< admonition title="tip" >}
+If you wish to bootstrap a remote system, you can use the `--host` option to
+specify the system. For example: `sparrowdo --host=192.168.1.2 --bootstrap`.
+{< / admonition >}
+
+Now your system is ready to be configured automatically using Sparrowdo!
+
+## Sparrowfiles
+
+Sparrowfiles are the files that describe the tasks Sparrow should execute to
+get you the configuration you want. They are valid Perl 6 code, and call the
+subroutines (or _sparrowtasks_) that will handle the actual actions. By default,
+when running `sparrowdo`, it will look for a file named `sparrowfile` in the
+current directory.
+
+To make our sample, we'll create a new directory to work in, so we have clean
+directory that can be shared easily. You can also keep this directory under
+version control, so you can distribute the `sparrowfile` with all its templates.
+
+{< admonition title="tip" >}
+If you just want to create an empty directory to test things in, without
+"polluting" the rest of your system, just call `cd -- "$(mktemp -d)"`. This will
+create a temporary directory and change the working directory to there.
+{< / admonition >}
+
+I'll be using `~/.local/sparrowdo/local-dns` to work in, as I'll be setting up a
+local dns cache with [http://www.thekelleys.org.uk/dnsmasq/doc.html](dnsmasq)
+for the sample code.
+
+### Writing a `sparrowfile`
+
+As noted in the previous paragraph, for the sake of a demo I'll guide you
+through creating a `sparrowfile` to install and configure `dnsmasq` as a local
+DNS cache. Using your favourite `$EDITOR`, write the following to `sparrowfile`:
+
+```raku
+package-install "dnsmasq";
+directory "/etc/dnsmasq.d";
+file-create "/etc/dnsmasq.conf", %(content => slurp "dnsmasq.conf");
+file-create "/etc/dnsmasq.d/resolv.conf", %(content => slurp "resolv.conf");
+service-start "dnsmasq";
+```
+
+This `sparrowfile` will set up the following configuration for `dnsmasq`:
+
+- Install the `dnsmasq` package
+- Create the `/etc/dnsmasq.d` directory in which we'll store configuration files
+ for `dnsmasq`
+- Create the configuration files `dnsmasq.conf` at `/etc/dnsmasq.conf`
+- Create the `resolv.conf` in the `dnsmasq.d` directory
+- Start the `dnsmasq` service
+
+The configuration files will be created based on the configuration files in the
+current directory. So for this to work, you'll need to also create the
+appropriate configuration files. Let's start off with the main `dnsmasq`
+configuration in `dnsmasq.conf`:
+
+```conf
+listen-address=127.0.0.1
+
+no-dhcp-interface=
+resolv-file=/etc/dnsmasq.d/resolv.conf
+```
+
+This will make `dnsmasq` listen on the loopback interface, so it'll only be able
+to be used by the local machine. Furthermore, DHCP functionality will be
+disabled, and the upstream resolvers are read from `/etc/dnsmasq.d/resolv.conf`.
+The contents of that file are as follows:
+
+```conf
+nameserver 37.235.1.174
+nameserver 37.235.1.177
+```
+
+These nameservers are part of the [https://freedns.zone/en/](FreeDNS) project.
+You can of course use whatever other DNS provider you want to use as your
+upstream servers. Now, for `dnsmasq` to be used, you will also need to set your
+machine's DNS resolvers to point to the `dnsmasq` service. This is defined in
+`/etc/resolv.conf`, so lets append the following to our `sparrowfile` to set
+that up.
+
+```conf
+bash "chattr -i /etc/resolv.conf";
+file-delete "/etc/resolv.conf";
+file-create "/etc/resolv.conf", %(content => "nameserver 127.0.0.1");
+bash "chattr +i /etc/resolv.conf";
+```
+
+This will remove the "immutable" attribute from `/etc/resolv.conf` if it's set.
+Next it will remove the current `/etc/resolv.conf` and write out a new one which
+only refers to the local machine as DNS resolver. This is to ensure an existing
+`/etc/resolv.conf` gets recreated with the configuration we want. Finally, it
+adds back the immutable attribute to the file, so other processes won't
+overwrite it.
+
+### Running the `sparrowfile`
+
+To run the `sparrowfile` and get the setup you desire, run the `sparrowdo`
+command with `--local_mode` and wait.
+
+```txt
+sparrowdo --local_mode
+```
+
+{< admonition title="note" >}
+If you want to run this on a remote machine to configure that one instead, you
+can use `--host=<ip>` instead of `--local_mode`.
+{< admonition >}
+
+You can check whether it actually worked by inspecting the files in
+`/etc/dnsmasq.d` and your `/etc/resolv.conf`. The easiest way to check their
+contents would be by using `cat`:
+
+```txt
+cat /etc/dnsmasq.d/dnsmasq.conf
+cat /etc/dnsmasq.d/resolv.conf
+cat /etc/resolv.conf
+```
+
+## Closing words
+
+You should now have a working local DNS setup, configured programmatically
+through Sparrowdo. This allows you easily get it working on other machines as
+well, and updates can be done in a much simpler fashion for all of them
+together.
+
+If you have more interest in automating configuration with Sparrowdo, go check
+their website, https://sparrowdo.wordpress.com/.
diff --git a/content/posts/2018/2018-08-15-the-perl-conference-in-glasgow.md b/content/posts/2018/2018-08-15-the-perl-conference-in-glasgow.md
new file mode 100644
index 0000000..0716bcc
--- /dev/null
+++ b/content/posts/2018/2018-08-15-the-perl-conference-in-glasgow.md
@@ -0,0 +1,304 @@
+---
+title: The Perl Conference in Glasgow
+date: 2018-08-23
+tags:
+- Conference
+- Perl
+---
+
+# The Perl Conference in Glasgow
+
+This year the European Perl Conference was hosted in Glasgow, and of course
+I've attended a number of presentations there. On some of these, I have some
+feedback or comments. These talks, and the feedback I have for them, are
+detailed in this blog post.
+
+{< admonition title="note" >}
+The first talk I cover is not so much about Perl, but more about politics, as
+the talk was mostly about the speaker's ideology. If this does not interest you,
+I'd suggest you skip the [#discourse-without-drama](Discourse Without Drama)
+section, and head straight to the
+[#european-perl-mongers-organiser-s-forum-2018](European Perl Mongers
+Organiser's Forum 2018).
+{< / admonition >}
+
+## Discourse Without Drama
+
+This was the first talk, and the only talk available at this timeslot. I am
+personally very much against the diversity ideology, and must admit I am
+skeptical of such presentations from the get-go. Nonetheless, I did stay until
+the end and tried to give it a fair shot. However, I cannot sit idle while she
+tries to force her ideology on this community I care very deeply about.
+
+{< admonition title="note" >}
+I am not against the concept of diversity, I wholly support the idea of equal
+opportunities. What I do not accept is the idea of equal outcome, or forced
+diversity based on physical traits. This is what I refer to with "the diversity
+ideology". I also don't think anyone has a right not to be offended, as this is
+impossible to achieve in the real world.
+{< / admonition >}
+
+One of the things that stood out to me is that the speaker tells us not to use
+logical fallacies to condemn her ideology. This on itself I can easily agree
+with. However, this should go both ways: we should also not use logical
+fallacies to promote her ideology. Most notably, she pointed out the
+[https://en.wikipedia.org/wiki/Argumentum_ad_populum](_argumentum ad populum_).
+This basically means that just because a lot of people do or say something,
+doesn't make it right. And this applies to the idea that we need to push the
+diversity ideology in the Perl community as well. Try to bring facts and
+statistics to show that this ideology will actually improve the community in
+the long term. I've personally not seen any community improve with increasingly
+harsh punishments for increasingly minor offenses.
+
+Another thing which slightly bothered me is the useless spin into radical
+feminist ideology, which to me seems very off-topic for a Perl conference.
+We're not at a political rally, and these kinds of remarks have been very
+divisive in all sorts of other environments already. I'd rather not bring this
+kind of behaviour to a community which I have loved for being so incredibly
+friendly without needing special rules and regulations for it.
+
+Next, a point is raised that people should *not* grow a thicker skin. Instead,
+people should get softer hearts. While I can get behind the latter part, I
+have to disagree with the former. Reality shows that communications don't
+always go perfectly. This is even more true in a community that exists mostly
+in the digital space. Context is often lost here, and that can lead to
+situations where someone may feel attacked even if this was not the intention
+at all. I can safely say I've been in many situations where my comments were
+perceived as an attack when they were not ment to be.
+
+People need to be able to handle some criticism, and sometimes you'll just have
+to assume good faith from the other party. Telling people they should never
+have to consider context and have a right not to be offended fosters an
+environment in which people will be afraid to give genuine, valid feedback.
+
+She seemed very much in favour of an overly broad code of conduct as well, of
+which I am also a strong opponent. There are various articles online, such as
+[https://shiromarieke.github.io/coc.html](this one), which show that just
+slapping a generic, vague code of conduct to a community isn't going to solve
+the issue of trolls or harmful behaviour. There's
+[http://quillette.com/2017/07/18/neurodiversity-case-free-speech/](another great
+article) that I was pointed towards that highlight how this attempt to censor
+people for the sake of not offending anyone can effectively halt creativity and
+the exchange of ideas. There was also an interesting quote written on one of
+the walls of the venue:
+
+{< quote attribution="Oscar Romero" >}
+Aspire not to have more, but to be more...
+{< / quote >}
+
+Don't try to add meaningless documents such as a code of conduct, which more
+often than not hurts a community instead of improving it. Try to be a better
+person that tries to solve actual issues without harming the community at large.
+Be the adult in the conversation that can take an insult, and still be kind.
+[https://rakudo.party/post/On-Troll-Hugging-Hole-Digging-and-Improving-Open-Source-Communities#hug2:feedthehandthatbitesyou](Remember
+to hug the trolls), and eventually they will hug you back.
+
+## European Perl Mongers Organiser's Forum 2018
+
+The Perl community isn't big nowadays, however, the Perl 6 language also offers
+a lot of concepts which are very well suited for modern programming. Sadly, if
+no new users try out the language, it will be all for nothing. As such, we need
+to bring new blood in to the community.
+
+One of the ways of doing this is by extending our promoting efforts outside of
+the Perl community. Most people who like Perl are in a social bubble with other
+people that are also familiar with the Perl programming language, be it 5 or 6.
+But we need to reach new people as well, who will most likely be outside of
+this social bubble. These people don't have to be techies either, they might
+just as well be marketeers or designers.
+
+I myself am part of the "techies", so I'll stick to this particular group for
+now. And I know people like me can be found at meetups, so it would be
+worthwhile to promote Perl at meetups which are not dedicated to Perl. Think of
+more generic programming meetups, or GNU+Linux User Groups. We have to be
+mindful not to be too pushy, though. Listen to other people, and try to
+understand the problem they're facing. Most of them will not be open to using a
+different language immediately, especially not Perl (which sadly has a
+particularly bad standing amongst people unfamiliar with it). Try to assist
+them with their issues, and slowly introduce them to Perl (6) if it helps to
+showcase what you mean. It might also be interesting to show people examples on
+how to solve certain issues before telling them the language's name, so they
+don't have a negative preconception solely from the name.
+
+Another thing to note is that Perl is more than just a programming language.
+It's a community, and a large library of modules, known as CPAN. And CPAN
+offers some nifty tools, such as the CPAN testers, which help ensure module
+developers that their code runs on a massive set of platforms and Perl
+versions.
+
+This has led me to consider the creation of a new Perl 6 module:
+`CPAN::Tester`, to make it easy for people to contribute to a large-scale
+testing environment for Perl 6. The idea is that one can run `CPAN::Tester` on
+their machine, which will keep track of new Perl 6 modules being uploaded to
+CPAN. The results are to be sent to another server (or multiple servers), which
+can aggregate the data and show a matrix of test results. This aggregating
+server could also be built as a Perl 6 module, possibly named
+`CPAN::Tester::ResultsServer`. This would make setting up an environment
+similar to CPAN testers for Perl 5 quite easy for Perl 6.
+
+## Perl 6 in Real Life $Work
+
+The speaker shows the perfect use case for
+[https://docs.perl6.org/language/grammars](Perl 6 grammars), advanced yet
+readable parsing of text and performing actions with the results. It's an
+interesting talk, showcasing some nifty grammar constructs. The best part of
+this is that it actually runs in production, where it parses over 700 files,
+consisting over 100,000 lines of code, in about 22 seconds (on his laptop).
+This goes to show that Perl 6 is no longer "too slow to use in production".
+
+It might be interesting to run this application of grammars on every Perl 6
+release to gather more information on the speed improvements of Perl 6, much
+like Tux's `Text::CSV` runs.
+
+## Releasing a Perl 6 Module
+
+The speaker starts off with detailing the platform which most Perl 6 modules
+use to host their code repository, GitHub. He also touched upon automated
+testing using Travis and AppVeyor. It was good to show how to make use of
+these, as automated testing oftentimes stops unintended bugs from reaching end
+users. But, I personally prefer GitLab over GitHub, as they have much better
+testing functionality, and they actually release their own platform as an open
+source package. I'd like more GitLab love from the community and speakers as
+well if possible. This would also make the speaker's CI configuration simpler,
+for which he currently uses a `.travis.yml` file. This requires him to build
+Perl 6 from source every test run, wasting quite a lot of time.
+
+It was also noted that there's a module to help you set up this module
+skeleton, `mi6`. The speaker also noted that it doesn't seem to add much once
+you know how a Perl 6 module is organized, and I tend to agree with this.
+Actually, I made a module precisely because I agree with him here,
+`App::Assixt`. This module intends to smoothen the entire course of module
+development, not just the creation of a skeleton file. It will take care of
+keeping your `META6.json` up to date, and ease uploading your module to CPAN as
+well.
+
+Lastly, the speaker says the `META6.json` documentation can be found in S22.
+While this is technically correct, S22 is *not* the implementation's
+documentation, this lives in the official Perl 6 documentation instead. S22
+offers many additional information to be stored in the `META6.json`, but using
+these fields will actually break installation of your module through `zef`,
+rendering it unusable by others. I would strongly recommend people not to use
+S22 when trying to figure out what they can or cannot do with their
+`META6.json`.
+
+## How to become CPAN contributor?
+
+Submitting a pull request (or more correctly named, merge request) to a
+repository is possibly the most straightforward way to help out other projects.
+However, sometimes it will take a long time to get a response. The speaker
+notes this can actually be on the scale of years. I have authored a number of
+modules myself, and have been in the situation where I had not realized I got a
+merge request from another person (same goes for issue reports). I would
+recommend people who are not getting timely responses to their contributions to
+contact the maintainer via other channels which are more suited for
+communications. Think of email or IRC, for instance. You'll generally have a
+much better chance of getting a timely response from the author, and then you
+can work out your contribution and see if you can get it merged into the main
+project.
+
+The speaker also lists a couple of ways to get started with contributing to
+modules. One thing I missed in particular was the Squashathons
+footnote:[A Squashathon is like a hackathon, except everyone in the world is
+invited, and you can help out over the Internet, staying in your own home. Of
+course, you can still meet up with other developers and make it a social
+gathering in the real world as well!] for Perl 6.
+These generally offer a good entry point to help out with the language's
+development and the ecosystem's maintainance.
+
+Near the end, it was pointed out that it is a good idea to have a thick skin.
+Even when it's not intended, people can come accross as rude. This is in
+opposition to the talking point of the speaker yesterday (_Discourse Without
+Drama_), but he does raise a good point here. People oftentimes don't mean to
+insult you, but context is easily lost in written communications. Try to stay
+mature and professional, you can simply ask for clarification. If you feel the
+person remains hostile towards you, walk away. There's plenty of other projects
+that would love your contributions!
+
+## Conference Organizers & European Perl Mongers Organiser's Forum 2018 BoF
+
+Well, that's certainly a mouthful for a heading, and it even contains an
+abbreviation! This event was not a presentation, but a platform to exchange
+ideas together.
+
+One of the items that were up for discussion was _A Conference Toolkit_, or ACT
+for short. This is the platform used to organize Perl events, such as this
+conference and Perl workshops throughout the world. However, ACT is dated.
+They enabled HTTPS a short while ago, but it's still not the default because
+people don't want to risk breaking the platform. I think this is enough of
+an indication that it might be time to make something new to replace it.
+
+And I'm not alone in that sentiment, it seems. However, ACT is big and contains
+a lot of data we don't want to lose. It's a massive undertaking to make a new
+tool that works at least as well, and allows us to make use of the old data as
+well. There is a Trello board available that lists all the features that would
+be required to implement, so that's a good start already. I think now it needs
+a dedicated product owner with people contributing code, so a start can be
+made. This does seem like a touchy subject, since I'm far from the first person
+to want this. Many before me have tried and failed already.
+
+As such, I'd propose not making it a Perl centric tool. Make it a modular,
+generic event organizing tool. Get a good database design that we can import
+our old data into, so nothing is lost, but things can be converted to be more
+useful for our current needs. This way, we can work in small steps, and maybe
+even reach contributors from outside the regular Perl circles. This might even
+bring in new partnerships (or sponsors) towards the Perl community.
+
+Personally, I'd like to see something like this to be written in Perl 6. This
+way, it could also be used as a showcase project for the Perl 6 programming
+language.
+
+## Writing a Perl 6 Module
+
+Perl 6 has this very neat feature called
+[https://docs.perl6.org/language/typesystem#index-entry-subset-subset](subsets).
+These can be used to make your own types with very little effort, which can
+help tremendously to keep your code clean and concise. There are two arguments
+I have in favour of subsets that the speaker did not touch upon.
+
+First off, using a subset instead of a `where` clause in a sub or method
+signature will bring much better error messages. If you use a `where` in your
+signature, and the check fails, you'll get an error that there was no signature
+that matched `where { ... }`.
+
+Secondly, if you want to use abstract methods, you can't really use a `where`.
+[https://stackoverflow.com/questions/51570655/how-to-use-abstract-multi-methods-containing-a-where](I've
+asked a question about this on Stack Overflow), which has the details as to why
+this doesn't work the way you might expect.
+
+Next, there's some cool things about operators in Perl 6. There are many of
+these available by default, and it's _very_ easy to add new ones yourself as
+well. In fact, the `Math::Matrix` module used throughout the presentation makes
+some available as well. Thanks to the ease of adding operators in Perl 6, if
+you have a `Math::Matrix $m` in Perl 6, you can get the norm by writing `|| $m
+||`. This is the mathematically correct way to write this, making it easy to
+understand for everyone using matrixes in their daily lives. If you're a
+mathematician, small things like these are great to have.
+
+I have some comments on the `Math::Matrix` module itself as well, based on
+slides shown in the presentiation. The first thing I noticed is that there's a
+`norm` method using a `where` clause when it's not needed:
+
+```raku
+method norm (Str $which where * eq 'row-sum')
+```
+
+This can be written instead as:
+
+```raku
+method norm ('row-sum')
+```
+
+This is shorter and clearer, and you'll get better feedback from the compiler
+as well. I [https://github.com/pierre-vigier/Perl6-Math-Matrix/pull/49](submitted
+a pull request on the GitHub repository) in an attempt to improve this, which
+got merged! The speaker was not aware it could be done in this manner, so I'm
+proud I got to teach him something right after he did his presentation.
+
+## Winding down
+
+I've had a great time at the Perl conference, spoke to many people with whom
+I've had some great discussions. I got to meet and personally thank a number of
+people who've helped me out over the past year as well.
+
+A big thank you to all the people who made this conference possible, and I hope
+to see you all again in Riga!
diff --git a/content/posts/2018/2018-09-04-setting-up-pgp-with-a-yubikey.md b/content/posts/2018/2018-09-04-setting-up-pgp-with-a-yubikey.md
new file mode 100644
index 0000000..314ba09
--- /dev/null
+++ b/content/posts/2018/2018-09-04-setting-up-pgp-with-a-yubikey.md
@@ -0,0 +1,443 @@
+---
+title: Setting up PGP with a Yubikey
+date: 2018-09-04
+tags:
+- GPG
+- PGP
+- Security
+- YubiKey
+---
+
+# Setting up PGP with a Yubikey
+
+I've recently started a job where I am required to have above-average security
+practices in place on my machine. I already had some standard security in
+place, such as full disk encryption and PGP encrypted email, but I thought that
+this would be a good time to up my game. To accomplish this, I purchased a
+Yubikey to act as my physical security token. Additionally, I have a USB device
+which is also encrypted to hold backups of the keys.
+
+In this blogpost, I will detail how I set up my security policies in the hopes
+it will be able to help out other people looking to improve their security, and
+to get feedback to improve my set up as well.
+
+{< admonition title="note" >}
+I am using the Yubikey 4. If you're using another version, some steps may
+differ.
+{< / admonition >}
+
+## Installing required software
+
+You'll need some software to set all of this up. Depending on your
+distribution, some of it might already be installed. Everything not installed
+yet should be installed with your distribution's package manager.
+
+For encrypting the disk and the USB key, you will need `cryptsetup`. To
+generate and use the PGP keys, you will need `gpg`, at least version 2.0.12. To
+interface with the Yubikey itself, you'll need `pcsc-lite`, and start the
+service as well. It may be necessary to restart the `gpg-agent` after
+installing `pcsc-lite`, which you can do by simply killing the existing
+`gpg-agent` process. It restarts itself when needed.
+
+To securely remove the temporary data we need, you should make sure you have
+`secure-delete` available on your system as well.
+
+## Personalizing the Yubikey
+
+The Yubikey can be personalized. Some of this personalization is completely
+optional, such as setting personal information. However, setting new PIN codes
+is strongly advised, as the default values are publicly known.
+
+### PIN codes
+
+The PIN codes are short combinations of numbers, letters and symbols to grant
+permission to write to or retrieve data from the Yubikey. The default value for
+the user PIN is `123456`. The admin PIN is `12345678` by default. These should
+be changed, as they're publicly known and allow the usage of your private keys.
+To change these, use the `gpg` program and enter admin mode:
+
+```txt
+gpg --card-edit
+
+gpg/card> admin
+Admin commands are allowed
+```
+
+You'll notice it immediately says that admin commands are now allowed to be
+used. The admin PIN (`12345678`) will be asked whenever an admin command is
+executed. It will then be stored for this session, so you won't have to enter
+it right away. To update the PIN values, run the following commands:
+
+```txt
+gpg/card> passwd
+gpg/card> 3
+```
+
+This will change the admin PIN first. This PIN is required for managing the
+keys and user PIN on the Yubikey. To set the user PIN, pick `1` instead of `3`:
+
+```txt
+gpg/card> 1
+```
+
+Once this is done, you can quit the `passwd` submenu using `q`:
+
+```txt
+gpg/card> q
+```
+
+You may have noticed we skipped the reset code. Resetting the device will wipe
+existing keys, so it's not a serious risk to keep this at the default. The
+private keys will be backed up to an encrypted USB drive, so we can always
+retrieve them and put them back on the Yubikey if ever needed.
+
+### Personal information
+
+The personal information is optional, but could be used by a friendly person to
+find out who a found Yubikey belongs to. They can contact the owner, and send
+the key back. You can set as many of the personally identifying fields as you
+want. If you're interested in setting this information, plug in your Yubikey
+and edit the card information with `gpg`:
+
+```txt
+gpg --card-edit
+```
+
+Once you're back in the GPG shell, you can update your personal information.
+There are 5 attributes that you can set in this way:
+
+- `name`, which is your real name;
+- `lang`, which is your preferred contact language;
+- `sex`, which is your real sex;
+- `url`, which indicates a location to retrieve your public key from;
+- `login`, which indicates your email address.
+
+Each of these attributes can be updated by running the command in the GPG
+shell. For instance, to update your real name, run the following:
+
+```txt
+gpg/card> name
+```
+
+You do not need to explicitly save once you're done. You can run `quit` to quit
+the GPG shell and return to your regular shell.
+
+## Creating PGP keys
+
+To create the PGP keys, we'll create a temporary directory which will function
+as our working directory to store the keys in. This way you can't accidentally
+break existing keys if you have them, and ensure that the private keys don't
+accidentally linger on in your filesystem.
+
+### Preparing a clean environment
+
+To create such a temporary directory, we'll use `mktemp`, and store the result
+in an environment variable so we can easily re-use it:
+
+```sh
+export GNUPGHOME="$(mktemp -d)"
+```
+
+Now you can switch to that directory using `cd "$GNUPGHOME"`. Additionally,
+`$GNUPGHOME` is also the directory `gpg` uses as its working directory, if it
+is set. This means you can use a temporary custom configuration for `gpg` as
+well, without it affecting your normal setup. The following configuration is
+recommended to set in `$GNUPGHOME/gpg.conf` before starting:
+
+```conf
+use-agent
+charset utf-8
+no-comments
+keyid-format 0xlong
+list-options show-uid-validity
+verify-options show-uid-validity
+with-fingerprint
+```
+
+If you have a `gpg-agent` running, it is recommended to stop it before
+continuing with `killall gpg-agent`.
+
+### Creating the master key
+
+For our master key, we'll go for a 4096 bytes RSA key. 2048 would be plenty as
+well, if you want the generation to be a tad quicker. `gpg` will ask you a
+couple questions to establish your identity, which is required for a PGP key.
+You can add more identities later, in case you're using multiple email
+addresses, for instance.
+
+Start the key generation process with `gpg`:
+
+```txt
+gpg --full-generate-key
+```
+
+When asked what kind of key you want, choose `4` (RSA (sign only)). Next is the
+key size, which should be `4096`.
+
+The key's expiration is optional, though highly recommended. It will be more
+effort to maintain the keys, as you'll occasionally need the private master
+keys to extend the validity, but you can also guarantee that your keys won't
+stay valid in case you ever lose them. If you don't want to bother with
+refreshing your keys from time to time, just press enter here to continue.
+
+When prompted on whether the data is correct, doublecheck whether the data is
+really correct, and then enter `y` and press enter to accept the current
+values. `gpg` will continue with your identity information, which you should
+fill out with your real information. The comment field can be left empty, this
+is an optional field to add a comment to your identity, such as "School", or
+"Work keys". `gpg` will ask your confirmation one final time. Enter an `o`
+(it's not case sensitive) and press enter again. The final step before it will
+generate a key is to enter a passphrase. This is technically optional, but
+highly recommended. If anyone ever gets their hands on your private master key,
+they will need the passphrase in order to use it. Adding one is yet another
+layer against malicious use of your key.
+
+Once you've chosen a passphrase, it will generate they key and output some
+information about the key. Verify whether this information is correct one more
+time, and if it is, you can continue to the next step. If it is not, redo the
+whole PGP section of this post.
+
+Take note of the line starting with `pub`. It shows that the key is an
+`rsa4096` key, followed by a `/`, and then the key ID. You'll need this key ID
+throughout the rest of this post. For convenience, you can store this ID in
+a variable, and just refer to the variable when you need it's value again:
+
+```sh
+export KEYID=0x27F53A16486878C7
+```
+
+This post will use the `$KEYID` variable from now on, to make it easier to
+follow.
+
+### Creating a revocation certificate
+
+The revocation certificate can be used to invalidate your newly created key.
+You should store it seperately from the private master key, preferably printed
+on a sheet of paper. If you want to be able to easily read it back in, consider
+printing it as a QR code.
+
+To create the certificate, run the following:
+
+```txt
+gpg --gen-revoke $KEYID > $GNUPGHOME/revoke.txt
+```
+
+This will prompt you to specify a reason, for which you'll want to use `1`.
+This way you can easily revoke the key's validity if you ever lose it. If you
+want to revoke your keys in the future for any other reason, you can always
+generate a new revocation certificate for that specific purpose. You don't have
+to supply an additional description, so just hit enter. A revocation
+certificate will be written to `$GNUPGHOME/revoke.txt`.
+
+### Creating the subkeys
+
+Now that you have your master key and the ability to revoke it in case anything
+goes wrong in the future, it's time to create a couple of subkeys which can be
+stored on the Yubikey, and used in your daily life. We'll create seperate keys
+for _encryption_, _signing_ and _authentication_, and store each of them in
+their own dedicated slot on the Yubikey.
+
+To add subkeys to your master key, enter a GPG shell to edit your existing
+key with `gpg --expert --edit-key $KEYID`. The `--expert` is required to show
+all the options we're going to need. Once the GPG shell has started, run
+`addkey` to add a new key.
+
+Just like with the master key, a number of questions will be asked. Expiration
+for subkeys is generally not advised, as the subkeys will be considered invalid
+whenever the master key has expired. The key sizes for the subkeys can be left
+at 2048 as well, which is also the maximum size for keys for the older Yubikey
+models. The key type is different for all 3 subkeys.
+
+You will want to select type `4` (RSA (sign only)) for your signing key, type
+`6` (RSA (encrypt only)) for the encryption key, and type `8` (RSA (set your
+own capabilities)) for the authentication key. With the final key, it will ask
+you what capabilities you want to enable. The only capability you want it to
+have is *Authentication*.
+
+Once you've created the subkeys, you can check `gpg --list-secret-keys` to look
+at your newly created keys. You should have 1 `sec` key, which is the master
+key, and 3 `ssb` keys, which are the subkeys. One line should end with `[S]`,
+one with `[E]` and one with `[A]`. These denote the capabilities of the
+subkeys, _Sign_, _Encrypt_ and _Authenticate_, respectively.
+
+### Export the keys
+
+Now that you have your keys generated, you should export them, allowing you to
+easily import them in another environment in case you ever need to generate
+more keys, invalidate some keys, or extend the validity of the keys in case you
+set an expiry date. This can be done with the following commands:
+
+```txt
+gpg --armor --export-secret-keys $KEYID > masterkey.asc
+gpg --armor --export-secret-subkeys $KEYID > subkeys.asc
+```
+
+## Creating a backup USB
+
+For the backup of the private keys, I'm using an encrypted USB device. You can
+also opt to print the keys to paper, and retype them if you ever need them. Or
+print a QR code that you can scan. But for convenience sake, I went with a USB
+device. I encrypted it, and stored it in a safe and sealed location, so it's
+easy to detect unwanted attempted access.
+
+### Encrypting the USB
+
+For the encryption, I went with full device encryption using LUKS. You will
+need the `cryptsetup` utility to apply the encryption, and to unlock the drive.
+You can find out the device name from `dmesg` or `lsblk`. Once you know it,
+encrypt the drive with the `luksFormat` subcommand.
+
+{< admonition title="warning" >}
+Using the wrong name for the device can irrecoverably destroy data from another
+drive!
+{< / admonition >}
+
+```txt
+cryptsetup luksFormat /dev/sdb
+```
+
+It will prompt you whether you want to continue, and ask twice for a passphrase
+to ensure it is correct. Make sure you don't forget the passphrase, or you'll
+lose access to your backup keys.
+
+Once it has been encrypted, unlock the device.
+
+```txt
+cryptsetup luksOpen /dev/sdb crypt
+```
+
+This will open the device as `/dev/mapper/crypt`. Format it with your favourite
+filesystem. I used `ext4`.
+
+```txt
+mkfs.ext4 /dev/mapper/crypt
+```
+
+Once it has been formatted, you can mount it as a regular device.
+
+```txt
+mount /dev/mapper/crypt /mnt/usb
+```
+
+### Copying the keys
+
+Copying the keys is as straightforward as copying other files. You can use
+`$GNUPGHOME` to target the source directory.
+
+```txt
+cp -arv "$GNUPGHOME"/* /mnt/usb/.
+```
+
+Once the files are copied, you can unmount the drive, lock it and unplug the
+USB.
+
+```txt
+sync
+umount /mnt/usb
+cryptsetup luksClose crypt
+```
+
+Store the USB in a safe location, because these private keys can give someone
+full control of your identity.
+
+## Storing the private keys on the Yubikey
+
+The Yubikey has key slots for encryption, signing and authentication. These
+need to be set individually, which can be done using `gpg`. First, you need to
+select a key using the `key` command, then store it on the card using
+`keytocard` and select a slot to store it in, then finally deselect the key by
+using the `key` command again.
+
+```txt
+gpg --edit-key $KEYID
+
+gpg> key 1
+gpg> keytocard
+Your selection? 1
+gpg> key 1
+
+gpg> key 2
+gpg> keytocard
+Your selection? 2
+gpg> key 2
+
+gpg> key 3
+gpg> keytocard
+Your selection? 3
+
+gpg> save
+```
+
+You can verify whether the keys are available on the Yubikey now using `gpg
+--card-status`. It will show the key fingerprints for the `Signature key`,
+`Encryption key` and `Authentication key`.
+
+### Sharing your public key
+
+You can share your public keys in many ways. Mine is hosted link:/pubkey.txt[on
+my own site], for instance. There are also https://sks-keyservers.net/[public
+keyservers] on which you can upload your keys. `gpg` has the `--send-keys` and
+`--recv-keys` switches to interact with these public keyservers. For ease of
+use, I would recommend uploading them to a public keyserver, so that other
+people can easily import it. For instance, my key can be imported using `gpg`:
+
+```txt
+gpg --recv-keys 0x7A6AC285E2D98827
+```
+
+## Clean up
+
+The keys are on the Yubikey, and you probably do not want to leave traces on
+your local system of these new keys, so you should clean up the `$GNUPGHOME`
+directory. There's a utility for securely removing a directory with all its
+contents, called `secure-delete`, which provides the `srm` program. You can use
+it just like the regular `rm` on the temporary directory.
+
+```txt
+srm -r "$GNUPGHOME"
+```
+
+You can also `unset` the `$GNUPGHOME` variable at this point, so `gpg` will use
+it's default configuration again.
+
+```txt
+unset GNUPGHOME
+```
+
+## Configure GPG
+
+Finally, you have your keys on the Yubikey and the traces that might have been
+left on your device are wiped clean. Now you should configure `gpg` for regular
+use as well, however, this is completely optional. All this configuration does
+is ensure you have good defaults for the current day and age.
+
+```conf
+auto-key-locate keyserver
+keyserver hkps://hkps.pool.sks-keyservers.net
+keyserver-options no-honor-keyserver-url
+personal-cipher-preferences AES256 AES192 AES CAST5
+personal-digest-preferences SHA512 SHA384 SHA256 SHA224
+default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5
+ZLIB BZIP2 ZIP Uncompressed
+cert-digest-algo SHA512
+s2k-cipher-algo AES256
+s2k-digest-algo SHA512
+charset utf-8
+fixed-list-mode
+no-comments
+no-emit-version
+keyid-format 0xlong
+list-options show-uid-validity
+verify-options show-uid-validity
+with-fingerprint
+use-agent
+require-cross-certification
+```
+
+## Conclusion
+
+You now have PGP keys available on your Yubikey. These keys are only available
+to your system if the Yubikey is inserted, and the user PIN is given. You can
+use these keys for authentication, signing and encrypting/decrypting messages.
+In a future post, I'll detail how to set up a number of services to use these
+keys as well.
diff --git a/content/posts/2018/2018-09-13-hackerrank-solutions-python3-and-perl6-part-1.md b/content/posts/2018/2018-09-13-hackerrank-solutions-python3-and-perl6-part-1.md
new file mode 100644
index 0000000..c7418e7
--- /dev/null
+++ b/content/posts/2018/2018-09-13-hackerrank-solutions-python3-and-perl6-part-1.md
@@ -0,0 +1,445 @@
+---
+title: "Hackerrank Solutions: Python 3 and Perl 6 (part 1)"
+date: 2018-09-13
+tags:
+- Hackerrank
+- Perl6
+- Python
+- Python3
+- Programming
+- Raku
+---
+
+# Hackerrank solutions: Python 3 and Perl 6 (part 1)
+
+I recently started at a new company, for which I will have to write Python 3
+code. To make sure I still know how to do basic stuff in Python, I started to
+work on some [https://www.hackerrank.com/](Hackerrank challenges). In this post,
+I will show solutions to some challenges to show the differences. I hope that I
+can show that Perl doesn't have to be the "write only" language that many
+people make it out to be.
+
+{< admonition title="note" >}
+I am _much_ more proficient in the Perl 6 programming language than in Python
+(2 or 3), so I might not always use the most optimal solutions in the Python
+variants. Suggestions are welcome via email, though I most likely won't update
+this post with better solutions. I ofcourse also welcome feedback on the Perl 6
+solutions!
+{< / admonition >}
+
+## Challenges
+
+The challenges covered in this post are the
+[https://www.hackerrank.com/domains/algorithms?filters%5Bsubdomains%5D%5B%5D=warmup](warmup
+challenges) you are recommended to solve when you make a new account. The code
+around the function I'm expected to solve won't be included, as this should be
+irrelevant (for now). Additionally, I may rename the sub to conform to
+[https://en.wikipedia.org/wiki/Letter_case#Special_case_styles](kebab-case), as
+this is more readable (in my opinion), and allowed in Perl 6.
+
+### Solve Me First
+
+This challenge is just a very simple example to introduce how the site works.
+It required me to make a simple `a + b` function.
+
+```python3
+def solveMeFirst(a,b):
+ return a+b
+```
+
+The Perl 6 variant isn't going to very different here.
+
+```raku
+sub solve-me-first ($a, $b) {
+ $a + $b
+}
+```
+
+For those not familiar with Perl 6, the `$` in front of the variable names is
+called a [https://docs.perl6.org/language/glossary#index-entry-Sigil](Sigil),
+and it signals that the variable contains only a single value.
+
+You may have noticed that there's also no `return` in the Perl 6 variant of
+this example. In Perl 6, the last statement in a block is also the implicit
+return value (just like in Perl 5 or Ruby).
+
+### Simple Array Sum
+
+For this challenge I had to write a function that would return the sum of a
+list of values. Naturally, I wanted to use a `reduce` function, but Python 3
+does not support these. So I wrote it with a `for` loop instead.
+
+```python3
+def simpleArraySum(ar):
+ sum = 0
+
+ for i in ar:
+ sum += i
+
+ return sum
+```
+
+Perl 6 does have a `reduce` function, so I would use that to solve the problem
+here.
+
+```raku
+sub simple-array-sum (@ar) {
+ @ar.reduce(sub ($a, $b) { $a + $b })
+}
+```
+
+Here you can see a different sigil for `@ar`. The `@` sigil denotes a list of
+scalars in Perl 6. In most other languages this would simply be an array.
+
+This code can be written even shorter, however. Perl 6 has
+[https://docs.perl6.org/language/operators#index-entry-%5B%2B%5D_%28reduction_metaoperators%29](reduction
+meta-operators). This allows you to put an operator between brackets, like
+`[+]`, to apply a certain operator as a reduce function.
+
+```raku
+sub simple-array-sum (@ar) {
+ [+] @ar
+}
+```
+
+{< admonition title="note" >}
+After publishing this post I have learned that both Python 3 and Perl 6 have a
+`.sum` function that can also be called on the array, simplifying the code in
+both languages.
+{< / admonition >}
+
+### Compare the Triplets
+
+This challenge provides you with 2 lists of 3 elements each. The lists should
+be compared to one another, and a "score" should be kept. For each index, if
+the first list contains a larger number, the first list's score must be
+incremented. Similarly, if the second list contains a larger number on that
+index, the second list's score must be incremented. If the values are equal, do
+nothing.
+
+```python3
+def compareTriplets(a, b):
+ scores = [0, 0]
+
+ for i in range(3):
+ if a[i] > b[i]:
+ scores[0] += 1
+
+ if a[i] < b[i]:
+ scores[1] += 1
+
+ return scores
+```
+
+I learned that Python 3 has no `++` operator to increment a value by 1, so I
+had to use `+= 1` instead.
+
+```raku
+sub compare-triplets (@a, @b) {
+ my @scores = [0, 0];
+
+ for ^3 {
+ @scores[0]++ if @a[$_] > @b[$_];
+ @scores[1]++ if @a[$_] < @b[$_];
+ }
+}
+```
+
+In Perl 6, the `^3` notation simply means a range from 0 to 3, non-inclusive,
+so `0`, `1`, `2`, meaning it will loop 3 times. The `$_` is called the
+_topic_, and in a `for` loop it is the current element of the iteration.
+
+Both of these loops could use a `continue` (or `next` in Perl 6) to skip the
+second `if` in case the first `if` was true, but for readability I chose not
+to.
+
+{< admonition title="note" >}
+After publishing this post I learned that Python 3 also supports the inline if
+syntax, just like Perl 6, so I could've used this in Python 3 as well.
+{< / admonition >}
+
+### A Very Big Sum
+
+In this challenge, you need to write the function body for `aVeryBigSum`, which
+gets an array of integers, and has to return the sum of this array. Both Python
+3 and Perl 6 handle the large integers transparently for you, so I was able to
+use the same code as I used for the simple array sum challenge.
+
+```python3
+def aVeryBigSum(ar):
+ sum = 0
+
+ for i in ar:
+ sum += i
+
+ return sum
+```
+
+And for Perl 6 using the `[+]` reduce meta-operation.
+
+```raku
+sub a-very-big-sum (@ar) {
+ [+] @ar
+}
+```
+
+### Plus Minus
+
+The next challenge gives a list of numbers, and wants you to return the
+fractions of its elements which are positive, negative or zero. The fractions
+should be rounded down to 6 decimals. I made a counter just like in the
+*Compare the Triplets* challenge, and calculated the fractions and rounded them
+at the end.
+
+```python3
+def plusMinus(arr):
+ counters = [0, 0, 0]
+
+ for i in arr:
+ if (i > 0):
+ counters[0] += 1
+ continue
+
+ if (i < 0):
+ counters[1] += 1
+ continue
+
+ counters[2] += 1
+
+ for i in counters:
+ print("%.6f" % (i / len(arr)))
+```
+
+For the Perl 6 solution, I went for a `given/when`, `map` and the `fmt`
+function to format the fractions.
+
+```raku
+sub plus-minus (@arr) {
+ my @counters = [0, 0, 0];
+
+ for @arr -> $i {
+ given $i {
+ when * > 0 { @counters[0]++ }
+ when * < 0 { @counters[1]++ }
+ default { @counters[2]++ }
+ }
+ }
+
+ @counters.map({ $_.fmt("%.6f").say });
+}
+```
+
+You may notice a number of statements do not have a terminating `;` at the end.
+In Perl 6, this is not needed if it's the last statement in a block (any code
+surrounded by a `{` and `}`.
+
+The `given/when` construct is similar to a `switch/case` found in other
+languages (but not Python, sadly), but uses the
+[https://docs.perl6.org/language/operators#index-entry-smartmatch_operator](smartmatch
+operator) implicitly to check if the statements given to `when` are `True`. The
+`*` is the [https://docs.perl6.org/type/Whatever](Whatever operator), which in
+this case will get the value of `$i`.
+
+Lastly, he `$_` in the `map` function is similar to inside a `for` loop,
+it's the current element. Since the code given to `map` is inside a block,
+there's no need for a `;` after `say` either.
+
+### Staircase
+
+This challenge gives you an integer 𝓃, and you're tasked with "drawing" a
+staircase that is 𝓃 high, and 𝓃 wide at the base. The staircase must be made
+using `#` characters, and for the spacing you must use regular spaces.
+
+It seems that in Python, you _must_ specify the `i in` part oft the `for i in
+range`. Since I don't really care for the value, I assigned it to `_`.
+
+```python3
+def staircase(n):
+ for i in range(1, n + 1):
+ for _ in range(n - i):
+ print(" ", end="")
+
+ for _ in range(i):
+ print("#", end="")
+
+ print("")
+```
+
+In Perl 6, there's also a `print` function, which is like `say`, but does not
+append a `\n` at the end of the string. The `for` loop in Perl 6 allows for
+just a range to operate as expected. The `..` operator creates a range from the
+left-hand side up to the right hand side, inclusive.
+
+```raku
+sub staircase ($n) {
+ for 1..$n -> $i {
+ print(" ") for 0..($n - $i);
+ print("#") for ^$i;
+ print("\n");
+ }
+}
+```
+
+### Mini-Maxi Sum
+
+Here you will be given 5 integers, and have to calculate the minimum and
+maximum values that can be calculated using only 4 of them.
+
+I sort the array, and iterate over the first 4 values to calculate the sum and
+print it. I then do the same but sort it in reverse for the sum of the 4
+highest values.
+
+```python3
+def miniMaxSum(arr):
+ arr.sort()
+ sum = 0
+
+ for i in range(4):
+ sum += arr[i]
+
+ print(str(sum) + " ", end="")
+
+ arr.sort(reverse=True)
+ sum = 0
+
+ for i in range(4):
+ sum += arr[i]
+
+ print(str(sum))
+```
+
+Perl 6 has immutable lists, so calling `sort` on them will return a new list
+which has been sorted. I can call `reverse` on that list to get the highest
+number at the top instead. `head` allows me to get the first 4 elements in a
+functional way. You've already seen the meta-reduce operator `[+]`, which will
+get me the sum of the 4 elements I got from `head`. I wrap the calculation in
+parenthesis so I can call `print` on the result immediately.
+
+```raku
+sub mini-maxi-sum (@arr) {
+ ([+] @arr.sort.head(4)).print;
+ print(" ");
+ ([+] @arr.sort.reverse.head(4)).print;
+}
+```
+
+### Birthday Cake Candles
+
+In this challenge, you're given a list of numbers. You must find the highest
+number in the list, and return how often that number occurs in the list.
+
+It's fairly straightforward, I keep track of the current largest value as
+`size`, and a `count` that I reset whenever I find a larger value than I
+currently have.
+
+```python3
+def birthdayCakeCandles(ar):
+ size = 0
+ count = 0
+
+ for i in ar:
+ if i > size:
+ size = i
+ count = 0
+
+ if i == size:
+ count += 1
+
+ return count
+```
+
+The Perl 6 variant does not differ in how it solves the problem, apart from
+having a very different syntax of course.
+
+```raku
+sub birthday-cake-candles (@ar) {
+ my ($size, $count) = (0, 0);
+
+ for @ar {
+ if ($_ > $size) {
+ $size = $_;
+ $count = 0;
+ }
+
+ $count++ if $size == $_;
+ }
+
+ $count;
+}
+```
+
+{< admonition title="note" >}
+On IRC, someone showed me a clean solution in Python 3: `return
+ar.count(max(ar))`. This feels like a much cleaner solution than what I had
+created.
+{< / admonition >}
+
+### Time Conversion
+
+This is the final challenge of this section on Hackerrank, and also this post.
+You're given a timestamp in 12-hour AM/PM format, and have to convert it to a
+24-hour format.
+
+I split the AM/PM identifier from the actual time by treating the string as a
+list of characters and taking two slices, one of the last two characters, and
+one of everything _but_ the last two characters. Then I split the time into
+parts, and convert the first part (hours) to integers for calculations. Next I
+set the hours to 0 if it's set to 12, and add 12 hours if the timestamp was
+post meridiem. Finally, I convert the hours back to a string with leading
+zeroes, and join all the parts together to form a timestamp again.
+
+```python3
+def timeConversion(s):
+ meridiem = s[-2:]
+ hours = int(s[:2])
+ rest = s[2:-2]
+
+ if (hours > 11):
+ hours = 0
+
+ if (meridiem.lower() == "pm"):
+ hours += 12
+
+ return ("%02d:%s" % (hours, rest))
+```
+
+The Perl 6 solution again doesn't differ much from the Python solution in terms
+of the logic it's using to get the result. The biggest difference is that in
+Perl 6, strings can't be accessed as lists, so I use the `substr` method to
+extract the parts that I want. The first one starts at `*-2`, which means 2
+places before the end. The others get a
+[https://docs.perl6.org/type/Range](`Range`) as argument, and will get the
+characters that exist in that range.
+
+```raku
+sub time-conversion ($s) {
+ my $meridiem = $s.substr(*-2);
+ my $hours = $s.substr(0..2).Int;
+ my $rest = $s.substr(2..*-2);
+
+ $hours = 0 if $hours > 11;
+ $hours += 12 if $meridiem.lc eq "pm";
+
+ sprintf("%02d:%s", $hours, $rest);
+}
+```
+
+The `.Int` method converts the `Str` object into an `Int` object, so we can
+perform calculations on it. The `eq` operator checks specifically for
+[https://docs.perl6.org/routine/eq](_string equality_). Since Perl 6 is a
+[https://en.wikipedia.org/wiki/Gradual_typing](gradually typed programming
+language), there's a dedicated operator to ensure that you're checking string
+equality correctly.
+
+## Wrap-up
+
+These challenges were just the warm-up challenges I was given after creating a
+new account and choosing Python as a language to use. I intend to write up more
+posts like this, for the near future I'll stick to Python 3 challenges since I
+want to get better at that specific language for work.
+
+This is also the first post in which I have tried this format to show off two
+languages side-by-side, and to highlight differences in how you can accomplish
+certain (relatively simple) tasks with them. If you have suggestions to improve
+this format, do not hesitate to contact me. I am always open for feedback,
+preferably via email. You can find my contact details on the [/](homepage).