Home > Raku > Contextual addition

Contextual addition

I took the absence of complaint as silent consent and set forth to implement HyperWhatever in associative subscripts. To do so I setup a little bit of tooling to lower cognitive load. When writing code I like to hit F1 in Vim and have it do the right thing depending on context. Since Vim is not self aware yet, we have to tell it what to do to help us. To specify context we can add a line to a source file to define a pseudo filetype.

use v6.*;
use Test;

# tests for the changes to Rakudo go here

# vim: ft=rakudotest

We can then define a filetype based mapping in ~/.vimrc.

autocmd FileType rakudotest nmap <F1> :w<CR>:!./testcase %<CR>

Since I change Rakudo I need to run a local copy by forking on Github and cloning into a fresh directory. There I can place a small shellscript.

#! /bin/sh

test 0 -lt $(find src/ -newer install/bin/raku -iname '*.pm6' | wc -l)\
&& make clean all test install

install/bin/raku $1

With this little chain I can edit Rakudo files and then hit F1 in the file with the tests. Rakudo will be rebuild and the test file executed with the local Rakudo instance. The latter needs to be prepared with perl ./Configure.pl --gen-moar --gen-nqp.

Since I wanted to put the new operators into v6.e I had to hunt down the spots where Rakudo needs the information what to put where. The new operator candidate goes into its own file in src/core.e/ which then has to be made known in tools/templates/6.e/core_sources. There are sanity test to avoid features to bleed from one version into another in t/02-rakudo/03-corekeys.t. This provided me with some bafflement, as institutional knowledge tends to do. I was mostly guided by error messages, which shows how important LTA is.

A few days ago we had a discussion about the one argument rule, where I claimed to have little difficulties with it. While implementing %your-hash{**}:deepkv I had to change my mind. The reason why the rule doesn’t bite me in practical code, is actually rooted in good testing.

    my $seen-J;
    my $seen-E;
    for %hash{**}:deepkv -> @deepkey, $value {
        $seen-J++ if @deepkey ~~ <J> && $value == 7;
        $seen-E++ if @deepkey ~~ <A D E> && $value == 3;
    }
    is $seen-J, 1, 'seen leaf in {**}:deepkv';
    is $seen-E, 1, 'seen deep leaf in {**}:deepkv';

Here the destructuring of the return value of %hash{**}:deepkv only works when the operator returns exactly the right thing.

multi sub postcircumfix:<{ }>( \SELF, HyperWhatever, :$deepkv!, *%other ) is raw {
    sub recurse(\v, @keys){
        if v ~~ Associative {
            for v.kv -> \k, \v {
                recurse v, [@keys.Slip, slip k]
            }
        }else{
            take slip(@keys, v)
        }
    }

    gather for SELF.kv -> \k, \v {
        if v ~~ Associative {
            recurse(v, [k])
        } else {
            take slip([k], v)
        }
    };
}

Getting the right amount of Slip into the right places took half an hour (building Rakudo takes about 60s) and plenty of cursing. I hope this is a case of torturing the implementer on behalf of the user. When using test driven code that seems to happen automatically. I’m to lazy too write a fancy test, so I have the testee to be clever enough to satisfy it.

Since I couldn’t find any documentation on how to add features in specific language versions, I hope this to be helpful to those who seek the same.

Categories: Raku
  1. No comments yet.
  1. July 12, 2021 at 20:40

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: