diff options
author | Paul "LeoNerd" Evans <leonerd@leonerd.org.uk> | 2021-11-20 16:40:59 +0000 |
---|---|---|
committer | Paul Evans <leonerd@leonerd.org.uk> | 2021-11-29 10:35:46 +0000 |
commit | 6a2e756f8693f753bad68e1827d8eee014636c86 (patch) | |
tree | dc1908e352075eaf47d2e34f8babff880ec18dd6 /lib | |
parent | 2a98b8cbbc6f75b5aaefb10acc4da4427359fcea (diff) | |
download | perl-6a2e756f8693f753bad68e1827d8eee014636c86.tar.gz |
Add a builtin:: namespace, with true/false/isbool
This finishes the perl-visible API required for RFC 0008
https://github.com/Perl/RFCs/blob/master/rfcs/rfc0008.md
It also begins the "builtin::" namespace of RFC 0009
https://github.com/Perl/RFCs/blob/master/rfcs/rfc0009.md
Diffstat (limited to 'lib')
-rw-r--r-- | lib/builtin.pm | 102 | ||||
-rw-r--r-- | lib/builtin.t | 78 |
2 files changed, 180 insertions, 0 deletions
diff --git a/lib/builtin.pm b/lib/builtin.pm new file mode 100644 index 0000000000..461f7ca5fe --- /dev/null +++ b/lib/builtin.pm @@ -0,0 +1,102 @@ +package builtin 0.001; + +use strict; +use warnings; + +# All code, including &import, is implemented by always-present functions in +# the perl interpreter itself. +# See also `builtin.c` in perl source + +1; +__END__ + +=head1 NAME + +builtin - Perl pragma to import built-in utility functions + +=head1 SYNOPSIS + + use builtin qw( true false isbool ); + +=head1 DESCRIPTION + +Perl provides several utility functions in the C<builtin> package. These are +plain functions, and look and behave just like regular user-defined functions +do. They do not provide new syntax or require special parsing. These functions +are always present in the interpreter and can be called at any time by their +fully-qualified names. By default they are not available as short names, but +can be requested for convenience. + +Individual named functions can be imported by listing them as import +parameters on the C<use> statement for this pragma. + +=head2 Lexical Import + +This pragma module creates I<lexical> aliases in the currently-compiling scope +to these builtin functions. This is similar to the lexical effect of other +pragmas such as L<strict> and L<feature>. + + sub classify + { + my $sv = shift; + + use builtin 'isbool'; + return isbool($sv) ? "boolean" : "not a boolean"; + } + + # the isbool() function is no longer visible here + # but may still be called by builtin::isbool() + +Because these functions are imported lexically, rather than by package +symbols, the user does not need to take any special measures to ensure they +don't accidentally appear as object methods from a class. + + package An::Object::Class { + use builtin 'true', 'false'; + ... + } + + # does not appear as a method + An::Object::Class->true; + + # Can't locate object method "true" via package "An::Object::Class" + # at ... + +=head1 FUNCTIONS + +=head2 true + + $val = true; + +Returns the boolean truth value. While any scalar value can be tested for +truth and most defined, non-empty and non-zero values are considered "true" +by perl, this one is special in that L</isbool> considers it to be a +distinguished boolean value. + +This gives an equivalent value to expressions like C<!!1> or C<!0>. + +=head2 false + + $val = false; + +Returns the boolean fiction value. While any non-true scalar value is +considered "false" by perl, this one is special in that L</isbool> considers +it to be a distinguished boolean value. + +This gives an equivalent value to expressions like C<!!0> or C<!1>. + +=head2 isbool + + $bool = isbool($val); + +Returns true when given a distinguished boolean value, or false if not. A +distinguished boolean value is the result of any boolean-returning builtin +function (such as C<true> or C<isbool> itself), boolean-returning operator +(such as the C<eq> or C<==> comparison tests or the C<!> negation operator), +or any variable containing one of these results. + +=head1 SEE ALSO + +L<perlop>, L<perlfunc>, L<Scalar::Util> + +=cut diff --git a/lib/builtin.t b/lib/builtin.t new file mode 100644 index 0000000000..003efd5ff2 --- /dev/null +++ b/lib/builtin.t @@ -0,0 +1,78 @@ +#!./perl + +BEGIN { + chdir 't' if -d 't'; + require './test.pl'; + set_up_inc('../lib'); +} + +use strict; +use warnings; + +# booleans +{ + use builtin qw( true false isbool ); + + ok(true, 'true is true'); + ok(!false, 'false is false'); + + ok(isbool(true), 'true is bool'); + ok(isbool(false), 'false is bool'); + ok(!isbool(undef), 'undef is not bool'); + ok(!isbool(1), '1 is not bool'); + ok(!isbool(""), 'empty is not bool'); + + my $truevar = (5 == 5); + my $falsevar = (5 == 6); + + ok(isbool($truevar), '$truevar is bool'); + ok(isbool($falsevar), '$falsevar is bool'); + + ok(isbool(isbool(true)), 'isbool true is bool'); + ok(isbool(isbool(123)), 'isbool false is bool'); +} + +# imports are lexical; should not be visible here +{ + my $ok = eval 'true()'; my $e = $@; + ok(!$ok, 'true() not visible outside of lexical scope'); + like($e, qr/^Undefined subroutine &main::true called at /, 'failure from true() not visible'); +} + +# lexical imports work fine in a variety of situations +{ + sub regularfunc { + use builtin 'true'; + return true; + } + ok(regularfunc(), 'true in regular sub'); + + my sub lexicalfunc { + use builtin 'true'; + return true; + } + ok(lexicalfunc(), 'true in lexical sub'); + + my $coderef = sub { + use builtin 'true'; + return true; + }; + ok($coderef->(), 'true in anon sub'); + + sub recursefunc { + use builtin 'true'; + return recursefunc() if @_; + return true; + } + ok(recursefunc("rec"), 'true in self-recursive sub'); + + my $recursecoderef = sub { + use feature 'current_sub'; + use builtin 'true'; + return __SUB__->() if @_; + return true; + }; + ok($recursecoderef->("rec"), 'true in self-recursive anon sub'); +} + +done_testing(); |