so
has very loose operator precedence, so we don't need parentheses here. The final two considerations are purely stylistic, but help for code maintaince. The names $a
, $b
, and $c
aren't descriptive. You'd definitely want to use something better. Also, it's fairly common, though not universal, to give extra emphasis to the fact that we're not mutating the values by using sigil-less variables. Personally, I also like to use whitespace to indicate the tighter grouping when using deconstruction, but YMMV. Lastly, semicolons aren't needed when they're the final expression of a block, or when a block terminates the line, so we can remove the semicolons.
sub circumfix:<α ω>( (\val,\min,\max) ) {
so min ≤ val.any ≤ max
};
sub circumfix:<α ω>( (\val where .all ~~ Int, \min where Int, \max where Int) --> Bool) {
so min ≤ val.any ≤ max
};
sub circumfix:<α ω> (
(
\val where .all ~~ Int,
\min where Int,
\max where Int
)
--> Bool
) {
so min ≤ val.any ≤ max
};
#| Determine if a value or values are between the given values (inclusive)
sub circumfix:<α ω> (
(
\val where .all ~~ Int, #= The Int value or values to be tested
\min where Int, #= The lowest acceptable value
\max where Int #= The highest acceptable value
)
--> Bool
) {
so min ≤ val.any ≤ max
};
so
has very loose operator precedence, so we don't need parentheses here. The final two considerations are purely stylistic, but help for code maintaince. The names $a
, $b
, and $c
aren't descriptive. You'd definitely want to use something better. Also, it's fairly common, though not universal, to give extra emphasis to the fact that we're not mutating the values by using sigil-less variables. Personally, I also like to use whitespace to indicate the tighter grouping when using deconstruction, but YMMV.
sub circumfix:<α ω>( (\val,\min,\max) ) {
so min ≤ val.any ≤ max
};
sub circumfix:<α ω>( (\val where .all ~~ Int, \min where Int, \max where Int) --> Bool) {
so min ≤ val.any ≤ max
};
sub circumfix:<α ω> (
(
\val where .all ~~ Int,
\min where Int,
\max where Int
)
--> Bool
) {
so min ≤ val.any ≤ max
};
#| Determine if a value or values are between the given values (inclusive)
sub circumfix:<α ω> (
(
\val where .all ~~ Int, #= The Int value or values to be tested
\min where Int, #= The lowest acceptable value
\max where Int #= The highest acceptable value
)
--> Bool
) {
so min ≤ val.any ≤ max
};
so
has very loose operator precedence, so we don't need parentheses here. The final two considerations are purely stylistic, but help for code maintaince. The names $a
, $b
, and $c
aren't descriptive. You'd definitely want to use something better. Also, it's fairly common, though not universal, to give extra emphasis to the fact that we're not mutating the values by using sigil-less variables. Personally, I also like to use whitespace to indicate the tighter grouping when using deconstruction, but YMMV. Lastly, semicolons aren't needed when they're the final expression of a block, or when a block terminates the line, so we can remove the semicolons.
sub circumfix:<α ω>( (\val,\min,\max) ) {
so min ≤ val.any ≤ max
}
sub circumfix:<α ω>( (\val where .all ~~ Int, \min where Int, \max where Int) --> Bool) {
so min ≤ val.any ≤ max
}
sub circumfix:<α ω> (
(
\val where .all ~~ Int,
\min where Int,
\max where Int
)
--> Bool
) {
so min ≤ val.any ≤ max
}
#| Determine if a value or values are between the given values (inclusive)
sub circumfix:<α ω> (
(
\val where .all ~~ Int, #= The Int value or values to be tested
\min where Int, #= The lowest acceptable value
\max where Int #= The highest acceptable value
)
--> Bool
) {
so min ≤ val.any ≤ max
}
AsYou mention potentially wanting to do multi
. That's certainly possible here:
multi sub circumfix:<α ω>( ( $a where Positional, $b, $c ) ) { ... };
multi sub circumfix:<α ω>( ( $a where Int, $b, $c ) ) { ... };
But ultimately it's unnecessary. As the other answer points out, Raku has a junction types built in. They can be made by using the routines (or operators) all
(&
), any
(|)
, one
(^
) and none
— the routines are available as both subs and methods. In your case, we can take advantage of the fact that junctions can be made on a single item or a list, so that regardless withwhether $a
is a list of Int
or just a single Int
, we can make it into a junction. That right there can reduce your code to:
As the other answer points out, Raku has a junction types built in. They can be made by using the routines (or operators) all
(&
), any
(|)
, one
(^
) and none
— the routines are available as both subs and methods. In your case, we can take advantage of the fact that junctions can be made on a single item or a list, so that regardless with $a
is a list of Int
or just a single Int
, we can make it into a junction. That right there can reduce your code to:
You mention potentially wanting to do multi
. That's certainly possible here:
multi sub circumfix:<α ω>( ( $a where Positional, $b, $c ) ) { ... };
multi sub circumfix:<α ω>( ( $a where Int, $b, $c ) ) { ... };
But ultimately it's unnecessary. As the other answer points out, Raku has a junction types built in. They can be made by using the routines (or operators) all
(&
), any
(|)
, one
(^
) and none
— the routines are available as both subs and methods. In your case, we can take advantage of the fact that junctions can be made on a single item or a list, so that regardless whether $a
is a list of Int
or just a single Int
, we can make it into a junction. That right there can reduce your code to:
There is quite a lot that you can do to make this idiomatic. I'll also go a bit overboard and show some ways to fully polish it (emphasis on way overboard for most projects).
As the other answer points out, Raku has a junction types built in. They can be made by using the routines (or operators) all
(&
), any
(|)
, one
(^
) and none
— the routines are available as both subs and methods. In your case, we can take advantage of the fact that junctions can be made on a single item or a list, so that regardless with $a
is a list of Int
or just a single Int
, we can make it into a junction. That right there can reduce your code to:
sub circumfix:<α ω>( ( $a, $b, $c ) ) {
so ( $a.any >= $b & $a.any <= $c );
};
Although we're going to remove it entirely, it should be noted that &
is a junction. This is slightly less efficient than using &&
which just checks whether both sides are true and evaluates to a Bool
. But we won't need to do that at all. Raku allows for chained operators, and the comparison operators are defined as such. This means that we can simplify things even further to:
sub circumfix:<α ω>( ( $a, $b, $c ) ) {
so $b ≤ $a.any ≤ $c;
};
so
has very loose operator precedence, so we don't need parentheses here. The final two considerations are purely stylistic, but help for code maintaince. The names $a
, $b
, and $c
aren't descriptive. You'd definitely want to use something better. Also, it's fairly common, though not universal, to give extra emphasis to the fact that we're not mutating the values by using sigil-less variables. Personally, I also like to use whitespace to indicate the tighter grouping when using deconstruction, but YMMV.
sub circumfix:<α ω>( (\val,\min,\max) ) {
so min ≤ val.any ≤ max
};
In this case, using min/max/val without sigils maybe is a bit riskier as they are also routines, but it seems to workout okay.
If we want to go above and beyond for safety's sake, we can check the values in the signature. I'm assuming based on your original that you wanted to limit things to Int
values so let's make it explicit, and specify our return value:
sub circumfix:<α ω>( (\val where .all ~~ Int, \min where Int, \max where Int) --> Bool) {
so min ≤ val.any ≤ max
};
At this point, the signature is getting a bit unruly, and so I like to spread it across multiple lines. Particularly if you have several deconstructed arguments, this lets identation also show structure a bit more clearly (but in this case, it's less necessary of course):
sub circumfix:<α ω> (
(
\val where .all ~~ Int,
\min where Int,
\max where Int
)
--> Bool
) {
so min ≤ val.any ≤ max
};
And don't forget that Raku's POD syntax means we can also add in documentation that could help users or automatically create documentation:
#| Determine if a value or values are between the given values (inclusive)
sub circumfix:<α ω> (
(
\val where .all ~~ Int, #= The Int value or values to be tested
\min where Int, #= The lowest acceptable value
\max where Int #= The highest acceptable value
)
--> Bool
) {
so min ≤ val.any ≤ max
};
IDEs like Comma are already able to pull some of this information to make coding easier. Using it on signatures is really only supported for generating help feedback automatically on command line usage, but it's only a matter of time before such things will be integrated into IDEs.