### Archive

Archive for August, 2022

## @data».sparkle

August 28, 2022 1 comment

While reading solutions to the PWC, I spotted a pattern. There where plenty of `.map`-calls that contained only simple maths. It must not be so! Task 179-2 leans itself to use vector operations.

``````use v6.d;

constant @sparks = "▁" .. "█";
constant \steps = +@sparks - 1;

multi MAIN(
#| space separated list of numbers
*@data
) {
my \$scale := @data.&{ (.max - .min) / steps };
put @sparks[((@data »-» @data.min) »/» \$scale)».round].join;
}

multi MAIN(
#| output an example sparkline-graph
Bool :\$test
) {
.&MAIN for <2 4 6 8 10 12 10 8 6 4 2>, <0 1 19 20>, <0 999 4000 4999 7000 7999>;
}``````

First, I define a character range (no need for `.ord` here) and store the number of bar-graph steps. Then I calculate the scale like it is used in a map (those paper-things, that always work and don’t break when dropped). Now I can use that scale to shrink (or grow) values. I believe rounding is better here then to cut of to integers.

When we feed a list to a `postcircumfix:<[ ]>` we get a list of values in return. However, we break the method-call chain when we do so. Since operators are just `Sub`s with a funny syntax, we can solve that issue easily.

``````constant &sparks = {
constant @sparks = "▁" .. "█";
constant \steps = +@sparks - 1;

&postcircumfix:<[ ]>.assuming(@sparks) but role :: { has \$.steps = steps }
}.();

my \$scale := @data.&{ (.max - .min) / &sparks.steps };
((@data »-» @data.min) »/» \$scale)».round.&sparks.join.put;``````

The constants are hidden within a block-scope and only `steps` is exposed as part of a `Sub`s “namespace”. By declaring `&sparks` as constant, I move the currying to compile time.

Hypers are not getting much use in PWC-solutions. I believe another entry in raku-did-you-know is in order.

Categories: Raku

## Suspicious introspection

One of my routines is acting suspicious. I’m almost certain it wilfully misinterprets arguments just so it can throw an exception. There is a way to spy on it.

``````sub suspicious(\$a, :\$b, *@rest, *%opts) {
die('imaoutahere!');

CATCH {
put (my \$sig = &?ROUTINE.signature.gist) ~ ' -> ' ~ \$sig.trans(<*@ *%> => <@ %>).EVAL».raku.join(',');
}
}

suspicious(1, :2b, 3,4,5);
# OUTPUT: (\$a, :\$b, *@rest, *%opts) -> 1,:b(2),3 4 5,
imaoutahere!
in sub suspicious at tmp/2021-03-08.raku line 1910
in block <unit> at tmp/2021-03-08.raku line 1917``````

Please note, that the `CATCH`-block doesn’t do anything to the exception. It is just there to trigger the debugging code. The proper place to put that would be a macro. Alas, `macro` can’t inject `CATCH`-blocks that are actually used as exception handlers. It will have to wait for RakuAST, what would also allow me to replace the EVAL-shenanigans with proper code. Another entry in `macro-ideas.txt` until then.

Categories: Raku

## Defeating definedness

August 18, 2022 1 comment

In his latest blogpost, p6steve went through a lot of trouble to enforce definedness. I managed to shorten it a bit.

``````None: Nil;
subset Option of Any where Any:D | None;

my Option \$defined = 42;
my Option \$nothing = None;
my Option \$undefined = Mu;

.&dd for \$defined, \$nothing, \$undefined;

# OUTPUT: Type check failed in assignment to \$undefined; expected Option but got Mu (Mu)``````

I would really like to see the content of `\$nothing`, and while I’m on it show why Steve’s hard labour was in vain.

``````try {
my Option \$defined = 42;
my Option \$nothing = None;
my Option \$undefined = Mu;

.&dd for \$defined, \$nothing, \$undefined;

CATCH { default { note .message; .resume } }
}

# OUTPUT: Type check failed in assignment to \$undefined; expected Option but got Mu (Mu)
#         Int \$defined = 42
#         Label \$nothing = Label.new(name => "None", file => "tmp/2021-03-08.raku", line => 1880)
#         Any \$undefined = Any``````

Raku is a dynamic, late bound language. There are language constructs, like resumable exceptions and NativeCall, that can defeat any type-check. Trying to use Raku like Rust, Haskell or any other strictly typed language will eventually fail. No amount of `:D`s will substitute testing, testing and even more testing.

I hope not to have tested p6steve’s patience and try to calm the waves with a new repo.

Categories: Raku

## Symbolism

August 14, 2022 1 comment

On IRC deoac wished to know how to print the name of a variable. This question is ambiguous. To get the name of the container is easy.

``````my \$foo;
say \$foo.VAR.name;
# OUTPUT: \$foo``````

If binding or constants involved, things get odd or fail.

``````my \$bar := \$foo;
constant \$never-changes = 'war';
# OUTPUT: \$foo
No such method 'name' for invocant of type 'Str'.  Did you mean any of
these: 'Date', 'Num', 'are', 'none', 'note', 'take'?``````

The second meaning of “variable” might be “symbol” for deoac’s use case. Getting hold of a symbol name requires early compile time measures.

``````use experimental :macros;
macro symbol-name(\$symbol) {
quasi { \$symbol.Str }
}

say symbol-name(\$foo);
say symbol-name(\$bar);
say symbol-name(\$never-changes);
# OUTPUT: (\$foo)
(\$bar)
(\$never-changes)``````

The value of `\$symbol` is an AST object and stringifies (in this case) to a list of `Str`. I didn’t dig deeper, because with RakuAST things will change.

However, this once again shows that we might do better by explaining what `my` actually does instead of assuming that one can guess what we mean when using the term “variable”.

Categories: Raku