<commit_before>use v6;
use Test;

plan 51;

{
    my @result = <a b c d e f g>.hyper.map({ $_.uc });
    is @result, <A B C D E F G>, "can hypermap a simple code block";

    @result = (^50).list.hyper.map({ $_ * 2 });
    is @result, (^50).map({$_*2}), "hyper over a big-ish list of Ints";
}

{
    my @result = (^50).list.hyper.map({ $_ * 2 }).map({ $_ div 2 });
    is @result, (^50).list, "two-stage map over big-ish Int list";

    @result = <a b c d e f g>.list.hyper.map({ $_.uc }).map({ $_ x 2 });
    is @result, <AA BB CC DD EE FF GG>, "two-stage map over some strings";
}

{
    my @result = (50..100).list.hyper.grep({ $_ %% 10 });
    is @result, (50, 60, 70, 80, 90, 100), "hyper + grep";
}

{
    my @result = (^100).list.hyper.grep({ $_.is-prime }).map({ $_ * $_ });
    is @result, (4, 9, 25, 49, 121, 169, 289, 361, 529, 841, 961, 1369, 1681, 1849, 2209, 2809, 3481, 3721, 4489, 5041, 5329, 6241, 6889, 7921, 9409), "hyper + grep + map";
}

#?rakudo.jvm skip 'hangs'
subtest '.hyper + map/grep keeps right order, when completed in reverse' => {
    plan 2;

    # We .keep last promise and then inside the hyper .keep previous ones,
    # so we end up keeping them in reverse
    (my @promises = ^5 .map: { Promise.new }).tail.keep;
    dd @promises[0].^name;
    my @result = ^5 .hyper( degree => 5, batch => 1 ).map: {
        await @promises[$_];        # wait our turn
        $_ && @promises[$_-1].keep; # allow the next lower one to proceed
        $_
    };
    is-deeply @result, [0, 1, 2, 3, 4], 'hyper + map';

    (@promises = ^5 .map: { Promise.new }).tail.keep;
    @result = ^5 .hyper( degree => 5, batch => 1 ).grep: {
        await @promises[$_];        # wait our turn
        $_ && @promises[$_-1].keep; # allow the next lower one to proceed
        True
    };
    is-deeply @result, [0, 1, 2, 3, 4], 'hyper + grep';
}

# RT #127191
{
    for <batch degree> -> $name {
        for (-1,0) -> $value {
            throws-like { ^10 .hyper(|($name => $value)) }, X::Invalid::Value,
              :method<hyper>, :$name, :$value,
              "cannot have a $name of $value for hyper";
        }
    }
}

# RT #127099
{
    my @res = ^1000 .hyper.map: *+0;
    is-deeply @res, [@res.sort], '.hyper preserves order';
}

# RT #127452
{
    for ^5 -> $i {
        my @x = ^10;
        my @y = @x.hyper(:3batch, :5degree).map: { sleep rand / 100; $_ + 1 };
        is @y, [1..10], ".hyper(:3batch, :5degree) with sleepy mapper works (try $i)";
    }
}
{
    for ^5 -> $i {
        my @x = (^10).hyper(:1batch).map: { sleep rand / 20; $_ };
        is @x, [^10], ".hyper(:1batch) with sleepy mapper works (try $i)";
    }
}
{
    my @a = 1, 3, 2, 9, 0, |( 1 .. 100 );
    for ^5 -> $i {
        my $a = @a.hyper.map: * + 1;
        is $a.list, (2, 4, 3, 10, 1, |( 2 .. 101 )),
            "Correct result of .hyper.map(*+1).list (try $i)";
    }
}
{
    my $b = Blob.new((^128).pick xx 1000);
    for ^5 {
        is $b[8..906].hyper.map({.fmt("%20x")}).list, $b[8..906].map({.fmt("%20x")}).list,
            '.hyper.map({.fmt(...)}) on a Buf slice works';
    }
}

# RT #129234
dies-ok { for (1..1).hyper { die } },
    "Exception thrown in hyper for is not lost (1..1)";
dies-ok { for (1..1000).hyper { die } },
    "Exception thrown in hyper for is not lost (1..1000)";
dies-ok { sink (1..1).hyper.map: { die } },
    "Exception thrown in hyper map is not lost (1..1)";
dies-ok { sink (1..1000).hyper.map: { die } },
    "Exception thrown in hyper map is not lost (1..1000)";
dies-ok { sink (1..1).hyper.grep: { die } },
    "Exception thrown in hyper grep is not lost (1..1)";
dies-ok { sink (1..1000).hyper.grep: { die } },
    "Exception thrown in hyper grep is not lost (1..1000)";

# RT #128084
{
    multi sub f ($a) { $a**2 }
    is (^10).hyper.map(&f).list, (0, 1, 4, 9, 16, 25, 36, 49, 64, 81),
        "hyper map with a multi sub works";
}

# RT #131865
#?rakudo.jvm skip 'atomicint NYI'
{
    my atomicint $got = 0;
    for <a b c>.hyper {
        $got⚛++
    }
    is $got, 3, 'for <a b c>.hyper { } actually iterates';
}

# RT #130576
is ([+] (1..100).hyper), 5050,
    'Correct result for [+] (1..100).hyper';
is ([+] (1..100).hyper.grep(* != 22)), 5028,
    'Correct result for [+] (1..100).hyper.grep(* != 22)';
is ([+] (1..100).grep(* != 22).hyper), 5028,
    'Correct result for [+] (1..100).grep(* != 22).hyper';
is (^100 .hyper.elems), 100, '.hyper.elems works';

#?rakudo.jvm skip 'atomicint NYI'
{
    my atomicint $i = 0;
    (^10000).hyper.map: { $i⚛++ }
    is $i, 10000, 'hyper map in sink context iterates';
}

{
    isa-ok (^1000).hyper.map(*+1).race, RaceSeq, 'Can switch from hyper to race mode';
    is (^1000).hyper.map(*+1).race.map(*+2).list.sort, (3..1002).list,
        'Switching from hyper to race mode does not break results';
}

{
    isa-ok (^1000).hyper.map(*+1).Seq, Seq, 'Can switch from hyper to sequential Seq';
    is (^1000).hyper.map(*+1).Seq.map(*+2).list, (3..1002).list,
        'Switching from hyper to sequential Seq does not break results or disorder';
}

is (^1000).hyper.is-lazy, False, 'is-lazy on HyperSeq returns False';

is-deeply (^3).hyper.Numeric, 3, '.Numeric on HyperSeq';
<commit_msg>[v6.d REVIEW] Simplify / test actual data<commit_after>use v6;
use Test;

plan 42;

is-deeply <a b c d e f g>.hyper.map({ $_.uc }).List,
    <A B C D E F G>, 'can hypermap a simple code block';

is-deeply ^50 .Seq.hyper.map(* × 2).Seq, ^50 .map(* × 2),
    'hyper over a big-ish list of Ints';

is-deeply ^50 .List.hyper.map(* × 2).map(* div 2).List, ^50 .List,
    'two-stage hyper map over big-ish Int list';

is-deeply <a b c d e f g>.hyper.map(*.uc).map(* x 2).List,
    <AA BB CC DD EE FF GG>, 'two-stage hyper map over some strings';

is-deeply (50..100).list.hyper.grep(* %% 10).List, (50, 60, 70, 80, 90, 100),
    'hyper + grep';

is-deeply ^100 .hyper.grep(*.is-prime).map(*²).List, (
    4, 9, 25, 49, 121, 169, 289, 361, 529, 841, 961, 1369, 1681, 1849,
    2209, 2809,  3481, 3721, 4489, 5041, 5329, 6241, 6889, 7921, 9409
), 'hyper + grep + map';

#?rakudo.jvm skip 'hangs'
subtest '.hyper + map/grep keeps right order, when completed in reverse' => {
    plan 2;

    # We .keep last promise and then inside the hyper .keep previous ones,
    # so we end up keeping them in reverse
    (my @promises = ^5 .map: { Promise.new }).tail.keep;
    dd @promises[0].^name;
    my @result = ^5 .hyper( degree => 5, batch => 1 ).map: {
        await @promises[$_];        # wait our turn
        $_ && @promises[$_-1].keep; # allow the next lower one to proceed
        $_
    };
    is-deeply @result, [0, 1, 2, 3, 4], 'hyper + map';

    (@promises = ^5 .map: { Promise.new }).tail.keep;
    @result = ^5 .hyper( degree => 5, batch => 1 ).grep: {
        await @promises[$_];        # wait our turn
        $_ && @promises[$_-1].keep; # allow the next lower one to proceed
        True
    };
    is-deeply @result, [0, 1, 2, 3, 4], 'hyper + grep';
}

# RT #127191
for <batch degree> -> $name {
    for (-1,0) -> $value {
        throws-like { ^10 .hyper(|($name => $value)) }, X::Invalid::Value,
          :method<hyper>, :$name, :$value,
          "cannot have a $name of $value for hyper";
    }
}

# RT #127099
is-deeply ^1000 .hyper.map(*+1).Array, [^1000 + 1], '.hyper preserves order';

# RT #127452
subtest '.hyper with .map that sleep()s' => {
    plan 10;

    is-deeply ^10 .hyper(:3batch, :5degree).map({
            sleep rand / 100; $_ + 1
        }).Array, [^10 + 1], ".hyper(:3batch, :5degree) [$_]"
    for ^5;

    is-deeply  ^10 .hyper(:1batch).map({ sleep rand / 20; $_ + 2 }).Array,
        [^10 + 2], ".hyper(:1batch) [$_]"
    for ^5;
}

{
    my @a = 1, 3, 2, 9, 0, |( 1 .. 100 );
    for ^5 -> $i {
        my $a = @a.hyper.map: * + 1;
        is $a.list, (2, 4, 3, 10, 1, |( 2 .. 101 )),
            "Correct result of .hyper.map(*+1).list (try $i)";
    }
}
{
    my $b = Blob.new((^128).pick xx 1000);
    for ^5 {
        is-deeply $b[8..906].hyper.map({.fmt("%20x")}).Seq,
                  $b[8..906]      .map({.fmt("%20x")}),
        '.hyper.map({.fmt(...)}) on a Buf slice works';
    }
}

# RT #129234
dies-ok { for (1..1).hyper { die } },
    "Exception thrown in hyper for is not lost (1..1)";
dies-ok { for (1..1000).hyper { die } },
    "Exception thrown in hyper for is not lost (1..1000)";
dies-ok { sink (1..1).hyper.map: { die } },
    "Exception thrown in hyper map is not lost (1..1)";
dies-ok { sink (1..1000).hyper.map: { die } },
    "Exception thrown in hyper map is not lost (1..1000)";
dies-ok { sink (1..1).hyper.grep: { die } },
    "Exception thrown in hyper grep is not lost (1..1)";
dies-ok { sink (1..1000).hyper.grep: { die } },
    "Exception thrown in hyper grep is not lost (1..1000)";

# RT #128084
{
    multi sub f ($a) { $a**2 }
    is-deeply (^10).hyper.map(&f).List, (0, 1, 4, 9, 16, 25, 36, 49, 64, 81),
        "hyper map with a multi sub works";
}

# RT #131865
#?rakudo.jvm skip 'atomicint NYI'
{
    my atomicint $got = 0;
    for <a b c>.hyper {
        $got⚛++
    }
    is $got, 3, 'for <a b c>.hyper { } actually iterates';
}

# RT #130576
is-deeply ([+] (1..100).hyper), 5050,
    'Correct result for [+] (1..100).hyper';
is-deeply ([+] (1..100).hyper.grep(* != 22)), 5028,
    'Correct result for [+] (1..100).hyper.grep(* != 22)';
is-deeply ([+] (1..100).grep(* != 22).hyper), 5028,
    'Correct result for [+] (1..100).grep(* != 22).hyper';
is-deeply (^100 .hyper.elems), 100, '.hyper.elems works';

#?rakudo.jvm skip 'atomicint NYI'
{
    my atomicint $i = 0;
    (^10000).hyper.map: { $i⚛++ }
    is $i, 10000, 'hyper map in sink context iterates';
}

{
    isa-ok (^1000).hyper.map(*+1).race, RaceSeq,
        'Can switch from hyper to race mode';
    is-deeply (^1000).hyper.map(*+1).race.map(*+2).List.sort, (3..1002).Seq,
        'Switching from hyper to race mode does not break results';
}

{
    isa-ok (^1000).hyper.map(*+1).Seq, Seq,
        'Can switch from hyper to sequential Seq';
    is-deeply (^1000).hyper.map(*+1).Seq.map(*+2).Seq, (3..1002).Seq,
        'hyper to sequential Seq switch does not break results or disorder';
}

is-deeply (^1000).hyper.is-lazy, False, 'is-lazy on HyperSeq returns False';
is-deeply (^3).hyper.Numeric, 3, '.Numeric on HyperSeq';

{'fraction_non_alphanumeric': 0.20905277533899133, 'fraction_numerical': 0.08330894546873475, 'mean_word_length': 2.441423296408191, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6678750', 'n_tokens_mistral': 4603, 'n_tokens_neox': 3944, 'n_words': 1227}