The Weekly Challenge in Raku : Week 72 (Part 2) 
Tags: raku
Published: 2020-08-04 08:27:24

---
title:  The Weekly Challenge in Raku : Week 72 (Part 2) 
published: true
description: The Weekly challenge in Raku : Week 72 (Part 2)
tags: raku
//cover_image: https://direct_url_to_image.jpg
---
So [Part 1](https://dev.to/scimon/the-weekly-challenge-in-raku-week-72-part-1-2i0g) was interesting and I've got a final coda to that. Here's probably the smallest and fastest way to solve the challenge.

    unit sub MAIN( UInt $N where * <= 10 );
    say '00000111112'.comb[$N];

...

Yup. So lets break this down. First up the [unit](https://docs.raku.org/syntax/unit) declarator says everything in the current file is part of the `MAIN` sub. It's not really required but I liked it.

`'00000111112'.comb` takes the string and splits it into a list. It's a bit shorter than writing the list with commas. Then we simply look up the index for `$N` in the list. 

This works because of the restriction on `$N` that it can't be greater than 10 so we can pre-calculate the results. This may seem like "cheating" but it's an important trick for a developer to have. Sometimes it's faster to pre-calculate and cache data than it to make it on the fly. 

Anyway onto the second task. 

## Task 2

So for this one I'm just going to share my whole answer and then go over what it's doing : 


    subset FilePath of Str where *.IO:f;
    
    #| Read and output lines A -> B in the given text file
    sub MAIN (
        UInt $A where * > 0, #= Start line
        UInt $B where * >= $A, #= End line
        FilePath :f(:$file) = "test-file.txt", #= Text file to read
    ) {
        .say for $file.IO.lines[$A-1..$B-1];
    }

Yes. The answer is 1 line of code. Everything else is validating input values, this is my favourite kind of function. Especially when the input validation is not done inside the function.

For the validation we firstly define a [subset](https://docs.raku.org/language/typesystem#index-entry-subset-subset) of the Str type. Subsets are effectively named [where clauses](https://docs.raku.org/type/Signature#index-entry-where_clause) which make the code easier to read and also make the computed Usage message nicer to read as well. 

The where clause casts our String to an IO object (treating it as a path) and then checks there's a file at that location. 

Note the UInt is a subset of Int and that as with `$A` and `$B` you can combine a subset and an additonal where clause. Also as in `$B` you can reference other parameters in your where clauses.

In all I love this signature for displaying the power of signatures in Raku it allows you to take a lot of the boiler plate for validation and shift it up, often allowing for compile time checking. 

And now the meat of the function. `$file.IO` makes an [IO::Path](https://docs.raku.org/type/IO::Path) object that points to the file we want to read. Then we call the [lines](https://docs.raku.org/routine/lines#class_IO::Path) method to get a sequence that returns lines in the file. (This is evaluated lazily which is nice).

Next we slice the sequence from `$A-1` (as the challenge specifies indexing from 1 and Raku indexes from 0) to `$B-1` and finally print each line with the `.say` method. When you call `for` and don't define the variable it uses `$_` and when you call a method without an object you use `$_` so bingo.

One of the things I love about Raku is it's ability to make things that you need to do often really really simple. Leaving you time to focus on the interesting problems.