develooper Front page | perl.beginners | Postings from June 2023

Re: type checks

Thread Previous | Thread Next
From:
sisyphus
Date:
June 3, 2023 12:16
Subject:
Re: type checks
Message ID:
CADZSBj3uG42R9x1YOvDvUQYW1Sc+P=R1mTPZMAe3yk0aGq5VHQ@mail.gmail.com
On Sat, Jun 3, 2023 at 6:41 PM Claude Brown <claude.brown@gigacomm.net.au>
wrote:

> Interesting.  I’d not used “B” before, so doing a little reading on that
> was fun, plus seeing how you had used it.
>
>
>
> Question: why did you have “is_ok” return 2 and 3, rather than just 1?
>

The way I've coded the "oload_*" subroutines there's a need to know whether
the second arg ($_[1]) is a Math::NumOnly object or a perl scalar.
Having is_ok return 1 for a Math::NumOnly object and a different value for
a valid perl scalar allows those subroutines to make that determination.

Of course, there's no apparent reason that we need to distinguish between
an IV (integer) scalar and an NV (float) scalar - so I could have just
returned "2" for both, rather than "2" for the IV and "3" for the NV.
(The OP's spec mentioned only integer values, and I initially considered
the possibility that there might be a need to distinguish between IVs and
NVs.)

And I must give credit where credit is due:
The B module stuff I used is stolen from:
https://metacpan.org/release/HAARG/Sub-Quote-2.006006/source/t/quotify.t

It has since occurred to me that there's a simpler solution that meets the
OP's spec - one that doesn't involve the creation of a specially designated
module.
Firstly, you just take the declaration of %flags as presented in
Math::NumOnly:
#########################
  use B;
  my %flags;
  {
    no strict 'refs';
    for my $flag (qw(
      SVf_IOK
      SVf_NOK
      SVf_POK
              )) {
      if (defined &{'B::'.$flag}) {
       $flags{$flag} = &{'B::'.$flag};
      }
    }
  }
#########################

However, you alter is_ok() to either return the numeric value of the scalar
(if that scalar satisfies the OP's spec); otherwise the sub croaks:

#########################
sub is_ok {
 die "Undefined value encountered" unless defined $_[0];
  my $val = shift;
  my $flags = flags($val);
  die "Bad value encountered" if $flags =~ /SVf_POK/;
  return $val
     if $flags =~ /SVf_IOK|SVf_NOK/;
  die "Bad value encountered";
}
#########################

Then, in your perl script, instead of doing:
$z = $x + $y;
you do:
$z = is_ok($x) + is_ok($y);

For example, the following code would result is $z being set to 7:
$x = 4;
$y = 3;
$z = is_ok($x) + is_ok($y);

But the following would die:
$x = 4;
$y = '3';
$z = is_ok($x) + is_ok($y);

Similarly, instead of doing:
$x += $y;
you would do:
is_ok($x) += is_ok($y);

and $x would be set to $x * $y if both $x and $y meet the spec; otherwise
the script dies.

Cheers,
Rob

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About