Raku Books / Creating a Compiler in Raku / Functions / Built-in functions

keys

The last built-in function on our list is keys. For a hash, it returns the list of its keys. As the internal order of a hash is not guaranteed, let us sort the keys before returning them. Among other things, that makes the function predictable and thus testable:

multi method call-function('keys', %var, AST::Variable $node
    where %var{$node.variable-name} ~~ Hash) {
    return %var{$node.variable-name}.keys.sort.List;
}

For an array, the natural counterpart is the list of its indices:

multi method call-function('keys', %var, AST::Variable $node
    where %var{$node.variable-name} ~~ Array) {
    return (0 ..^ %var{$node.variable-name}.elems).List;
}

The ..^ operator creates a range that excludes its right end. In other words, for a three-element array, we get the indices 0, 1, and 2.

The function returns a Raku List, and the say function does not yet know how to print one nicely. One more gist candidate solves that:

multi method gist(%var, ASTNode $value where $value.value ~~ List) {
    return $value.value.join(', ');
}

There is one more place where a list can appear: as an argument of another function. What is the length of a list of keys? The generic len candidate converts its argument to a string and counts the characters, which is not what anyone expects. A special variant for lists fixes it:

multi method call-function('len', %var, ASTNode $node
    where $node.value ~~ List) {
    return $node.value.elems;
}

Now the functions compose nicely, and the test file confirms it:

my h{} = "beta": 2, "alpha": 1, "gamma": 3;
say keys h; ## alpha, beta, gamma
my a[] = 10, 20, 30;
say keys a; ## 0, 1, 2
say len keys h; ## 3

Course navigation

len   |   User-defined functions