``````use Carp;
use Switch qw(Perl6 __ fallthrough);

my(\$C,\$M);sub ok{\$C++;\$M.=\$_[0]?"ok \$C\n":"not ok \$C (line ".(caller)[2].")\n"}
END{print"1..\$C\n\$M"}

# NON-when THINGS;

\$when->{when} = { when => "when" };

*when = \&when;

# PREMATURE when

eval { when 1 { ok(0) }; ok(0) } || ok(1);

# H.O. FUNCS

given 2 {

when __ < 1	{ ok(0) } else { ok(1) }
when __ < 2	{ ok(0) } else { ok(1) }
when __ < 3	{ ok(1) } else { ok(0) }
}

given (3) {

eval { when __ <= 1 || __ > 2	{ ok(0) } } || ok(1);
when __ <= 2 		{ ok(0) };
when __ <= 3		{ ok(1) };
}

# POSSIBLE ARGS: NUMERIC, STRING, ARRAY, HASH, REGEX, CODE

# 1. NUMERIC SWITCH

for (1..3)
{
given (\$_) {
# SELF
when (\$_) { ok(1) } else { ok(0) }

# NUMERIC
when 1 { ok (\$_==1) } else { ok(\$_!=1) }
when (1)  { ok (\$_==1) } else { ok(\$_!=1) }
when 3 { ok (\$_==3) } else { ok(\$_!=3) }
when (4) { ok (0) } else { ok(1) }
when (2) { ok (\$_==2) } else { ok(\$_!=2) }

# STRING
when ('a') { ok (0) } else { ok(1) }
when  'a'  { ok (0) } else { ok(1) }
when ('3') { ok (\$_ == 3) } else { ok(\$_ != 3) }
when ('3.0') { ok (0) } else { ok(1) }

# ARRAY
when ([10,5,1]) { ok (\$_==1) } else { ok(\$_!=1) }
when  [10,5,1]  { ok (\$_==1) } else { ok(\$_!=1) }
when (['a','b']) { ok (0) } else { ok(1) }
when (['a','b',3]) { ok (\$_==3) } else { ok (\$_!=3) }
when (['a','b',2.0])  { ok (\$_==2) } else { ok (\$_!=2) }
when ([])  { ok (0) } else { ok(1) }

# HASH
when ({})  { ok (0) } else { ok (1) }
when {}  { ok (0) } else { ok (1) }
when {1,1}  { ok (\$_==1) } else { ok(\$_!=1) }
when ({1=>1, 2=>0})  { ok (\$_==1) } else { ok(\$_!=1) }

# SUB/BLOCK
when (sub {\$_[0]==2})  { ok (\$_==2) } else { ok(\$_!=2) }
when {\$_[0]==2}  { ok (\$_==2) } else { ok(\$_!=2) }
when {0}  { ok (0) } else { ok (1) }	# ; -> SUB, NOT HASH
when {1}  { ok (1) } else { ok (0) }	# ; -> SUB, NOT HASH
}
}

# 2. STRING SWITCH

for ('a'..'c','1')
{
given (\$_) {
# SELF
when (\$_)  { ok(1) } else { ok(0) }

# NUMERIC
when (1)   { ok (\$_ !~ /[a-c]/) } else { ok (\$_ =~ /[a-c]/) }
when (1.0)  { ok (\$_ !~ /[a-c]/) } else { ok (\$_ =~ /[a-c]/) }

# STRING
when ('a')  { ok (\$_ eq 'a') } else { ok(\$_ ne 'a') }
when ('b')  { ok (\$_ eq 'b') } else { ok(\$_ ne 'b') }
when ('c')  { ok (\$_ eq 'c') } else { ok(\$_ ne 'c') }
when ('1')  { ok (\$_ eq '1') } else { ok(\$_ ne '1') }
when ('d')  { ok (0) } else { ok (1) }

# ARRAY
when (['a','1'])  { ok (\$_ eq 'a' || \$_ eq '1') }
else { ok (\$_ ne 'a' && \$_ ne '1') }
when (['z','2'])  { ok (0) } else { ok(1) }
when ([])  { ok (0) } else { ok(1) }

# HASH
when ({})  { ok (0) } else { ok (1) }
when ({a=>'a', 1=>1, 2=>0})  { ok (\$_ eq 'a' || \$_ eq '1') }
else { ok (\$_ ne 'a' && \$_ ne '1') }

# SUB/BLOCK
when (sub{\$_[0] eq 'a' })  { ok (\$_ eq 'a') }
else { ok(\$_ ne 'a') }
when {\$_[0] eq 'a'}  { ok (\$_ eq 'a') } else { ok(\$_ ne 'a') }
when {0}  { ok (0) } else { ok (1) }	# ; -> SUB, NOT HASH
when {1}  { ok (1) } else { ok (0) }	# ; -> SUB, NOT HASH
}
}

# 3. ARRAY SWITCH

my \$iteration = 0;
for ([],[1,'a'],[2,'b'])
{
given (\$_) {
\$iteration++;
# SELF
when (\$_)  { ok(1) }

# NUMERIC
when (1)  { ok (\$iteration==2) } else { ok (\$iteration!=2) }
when (1.0)  { ok (\$iteration==2) } else { ok (\$iteration!=2) }

# STRING
when ('a')  { ok (\$iteration==2) } else { ok (\$iteration!=2) }
when ('b')  { ok (\$iteration==3) } else { ok (\$iteration!=3) }
when ('1')  { ok (\$iteration==2) } else { ok (\$iteration!=2) }

# ARRAY
when (['a',2])  { ok (\$iteration>=2) } else { ok (\$iteration<2) }
when ([1,'a'])  { ok (\$iteration==2) } else { ok(\$iteration!=2) }
when ([])  { ok (0) } else { ok(1) }
when ([7..100])  { ok (0) } else { ok(1) }

# HASH
when ({})  { ok (0) } else { ok (1) }
when ({a=>'a', 1=>1, 2=>0})  { ok (\$iteration==2) }
else { ok (\$iteration!=2) }

# SUB/BLOCK
when {scalar grep /a/, @_}  { ok (\$iteration==2) }
else { ok (\$iteration!=2) }
when (sub {scalar grep /a/, @_ })  { ok (\$iteration==2) }
else { ok (\$iteration!=2) }
when {0}  { ok (0) } else { ok (1) }	# ; -> SUB, NOT HASH
when {1}  { ok (1) } else { ok (0) }	# ; -> SUB, NOT HASH
}
}

# 4. HASH SWITCH

\$iteration = 0;
for ({},{a=>1,b=>0})
{
given (\$_) {
\$iteration++;

# SELF
when (\$_)  { ok(1) } else { ok(0) }

# NUMERIC
when (1)  { ok (0) } else { ok (1) }
when (1.0)  { ok (0) } else { ok (1) }

# STRING
when ('a')  { ok (\$iteration==2) } else { ok (\$iteration!=2) }
when ('b')  { ok (0) } else { ok (1) }
when ('c')  { ok (0) } else { ok (1) }

# ARRAY
when (['a',2])  { ok (\$iteration==2) }
else { ok (\$iteration!=2) }
when (['b','a'])  { ok (\$iteration==2) }
else { ok (\$iteration!=2) }
when (['b','c'])  { ok (0) } else { ok (1) }
when ([])  { ok (0) } else { ok(1) }
when ([7..100])  { ok (0) } else { ok(1) }

# HASH
when ({})  { ok (0) } else { ok (1) }
when ({a=>'a', 1=>1, 2=>0})  { ok (0) } else { ok (1) }

# SUB/BLOCK
when {\$_[0]{a}}  { ok (\$iteration==2) }
else { ok (\$iteration!=2) }
when (sub {\$_[0]{a}})  { ok (\$iteration==2) }
else { ok (\$iteration!=2) }
when {0}  { ok (0) } else { ok (1) }	# ; -> SUB, NOT HASH
when {1}  { ok (1) } else { ok (0) }	# ; -> SUB, NOT HASH
}
}

# 5. CODE SWITCH

\$iteration = 0;
for ( sub {1},
sub { return 0 unless @_;
my (\$data) = @_;
my \$type = ref \$data;
return \$type eq 'HASH'   && \$data->{a}
|| \$type eq 'Regexp' && 'a' =~ /\$data/
|| \$type eq ""       && \$data eq '1';
},
sub {0} )
{
given (\$_) {
\$iteration++;
# SELF
when (\$_)  { ok(1) } else { ok(0) }

# NUMERIC
when (1)  { ok (\$iteration<=2) } else { ok (\$iteration>2) }
when (1.0)  { ok (\$iteration<=2) } else { ok (\$iteration>2) }
when (1.1)  { ok (\$iteration==1) } else { ok (\$iteration!=1) }

# STRING
when ('a')  { ok (\$iteration==1) } else { ok (\$iteration!=1) }
when ('b')  { ok (\$iteration==1) } else { ok (\$iteration!=1) }
when ('c')  { ok (\$iteration==1) } else { ok (\$iteration!=1) }
when ('1')  { ok (\$iteration<=2) } else { ok (\$iteration>2) }

# ARRAY
when ([1, 'a'])  { ok (\$iteration<=2) }
else { ok (\$iteration>2) }
when (['b','a'])  { ok (\$iteration==1) }
else { ok (\$iteration!=1) }
when (['b','c'])  { ok (\$iteration==1) }
else { ok (\$iteration!=1) }
when ([])  { ok (\$iteration==1) } else { ok(\$iteration!=1) }
when ([7..100])  { ok (\$iteration==1) }
else { ok(\$iteration!=1) }

# HASH
when ({})  { ok (\$iteration==1) } else { ok (\$iteration!=1) }
when ({a=>'a', 1=>1, 2=>0})  { ok (\$iteration<=2) }
else { ok (\$iteration>2) }

# SUB/BLOCK
when {\$_[0]->{a}}  { ok (0) } else { ok (1) }
when (sub {\$_[0]{a}})  { ok (0) } else { ok (1) }
when {0}  { ok (0) } else { ok (1) }	# ; -> SUB, NOT HASH
when {1}  { ok (0) } else { ok (1) }	# ; -> SUB, NOT HASH
}
}

# NESTED SWITCHES

for my \$count (1..3)
{
given ([9,"a",11]) {
when (qr/\d/)  {
given (\$count) {
when (1)      { ok(\$count==1) }
else { ok(\$count!=1) }
when ([5,6])  { ok(0) } else { ok(1) }
}
}
ok(1) when 11;
}
}
``````