Re: RFC: utils.pm
From: Tore Aursand (tore_at_aursand.no)
Date: 02/11/04
- Next message: Jeff 'japhy' Pinyan: "Re: Using Tie::IxHash order a hash reference"
- Previous message: gibbering poster: "TK Help with Canvas"
- In reply to: Ben Morrow: "Re: RFC: utils.pm"
- Next in thread: Uri Guttman: "Re: RFC: utils.pm"
- Reply: Uri Guttman: "Re: RFC: utils.pm"
- Reply: Ben Morrow: "Re: RFC: utils.pm"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Wed, 11 Feb 2004 20:36:05 +0100
On Wed, 11 Feb 2004 15:23:37 +0000, Ben Morrow wrote:
>> split_csv( $value ) - Easy CSV splitting. (*)
> As you say, there are modules to do this. Or
>
> @values = split /,/, $values;
Not quite as powerful as this one;
my @array = ();
push( @array, $+ ) while $string =~ m{
"([^\"\\]*(?:\\.[^\"\\]*)*)",? # groups the phrase inside the quotes
| ([^,]+),?
| ,
}gx;
push( @array, undef ) if ( substr($string, -1, 1) eq ',' );
>> random_string( $length ) - Generates a random string $length
>> characters long.
> This is a little harder... also *much* less useful.
Maybe, but I find myself constantly using this one when I want to create
cookies. Nice to have. :)
>> as_string( $value, [$default] ) - Always returns a defined value,
>> optionally $default if $value
>> isn't defined.
> Eh what? You don't *need* to cast in Perl.
>
> $value || $default
This only returns $default if $value isn't true. So if we have this
function:
sub as_string {
my $value = shift;
my $default = shift;
return $value || $default;
}
What happens when you pass 0 to this function?
> or defined($value) ? $value : $default
Better, but I'm tired to writing this god damn line each time I want to
make sure that a value is defined. :)
My 'as_string' function will only return the $default value if a) it is
given, and b) if the input $value is undefined.
When it comes to "casting". Maybe it's not the correct word to use, but
when dealing with ie. CGI parameters, I find my functions useful. Here's
an example;
my $firstname = as_string( $cgi->param('firstname') );
my $lastname = as_string( $cgi->param('lastname') );
my $age = as_int( $cgi->param('age') );
>> as_int( $value ) - Always returns $value as an integer.
> err.. int($value)
What if $value isn't a number? Ah. A warning occurs, of course. I don't
want warnings. 'as_int' clearly says that I want _any_ value passed to it
returned as an integer. If that's not possible, return 0.
> Or POSIX::floor, or POSIX::ceil.
I know about them. I just didn't want to deal with more than one module,
so I created my own functions instead. :)
>> as_decimal( $value, [$decimals] ) - Always returns $value as a
>> decimal number with $decimals
>> numbers after the decimal point.
> sprintf
Excactly what 'as_decimal' uses, except that I prefer writing
my $value = as_decimal( 1.23456789, 2 );
instead of
my $value = sprintf( '%.2f', 1.23456789 );
>> as_boolean( $value ) - Always returns $value as a boolena value (ie.
>> TRUE/1 or FALSE/0).
> !!$value
Yeah, but 'as_boolean' takes care of "other" boolean values to;
sub as_boolean {
my $value = as_string( shift );
return ( $value =~ m,^1|y|yes|on|true$,i ) ? 1 : 0;
}
I needed this function when dealing with output from an application where
a true value could be almost anything.
No, I didn't write that program, and it wasn't in Perl (or any other
interpreted language), so I couldn't change the output.
>> as_date( $value ) - Always returns $value as a date (YYYY-MM-DD).
>> as_time( $value ) - Always returns $value as a time (HH:MM:SS).
>> as_datetime( $value ) - Always returns $value as a datetime (which
>> means combining as_date() and as_time()).
> POSIX::strftime
'as_date', 'as_time' and 'as_datetime' are - of course - a lot easier to
use than 'strftime'. :)
I don't use the 'strftime' much, and every time I had to use it, I had to
look it up in the documentation. I don't want to do that. I'm lazy. :)
>> VALIDATION
>> Each of the CASTING functions also have a is_* function, which returns
>> TRUE/1 or FALSE/0 depending on wether the input argument conforms to
>> the datatype.
> Ummm... everything is (can be) a string.
Yes, but not everything can be everything _else_ than a string. Let's
look at my CGI parameter example again. Instead of writing
my $nr = (defined $cgi->param('nr')) ? $cgi->param('nr') : 0;
unless ( $nr >= 0 && $nr <= 12 ) {
# Error
}
I want to write
my $nr = as_int( $cgi->param('nr') );
unless ( is_int($nr, 0, 12) ) {
# Error
}
> is_int is simply $value =~ /^\d+$/.
No. Take a look at this:
my @values = ( 2, -2, +2, '2', '-2', '+2' );
foreach ( @values ) {
print "Is $_ an integer? ";
( /^\d+$/ ) ? print 'Yes' : print 'No';
print "\n";
}
Of course, one could argue about wether a stringified '-2' (or '+2')
really is an integer, but functions like these are nice to have if you
want to _avoid_ errors:
# $value appears from somewhere, possibly from a stupid user :)
if ( is_int($value) ) {
# Ok, we can use this value
$value = as_int( $value ); # 'Cast' it to integer
}
else {
# Sorry, but $value isn't even close to being an integer
}
> Dates can and should be handled by your favourite date-time parsing
> module: the code is non-trivial, so should be reused.
I guess you're right. I created many of them (the functions) "by hand",
though, and tested them agains Date::Calc and Date::Manip. Man, that was
one useful learning session. :)
> I can't think offhand how I'd do is_decimal, probably because I've
> never had occasion to.
I once (...) encountered a problem with a web form where the user had to
register some data, and he/she _had_ to enter a number as a decimal. That
was to make sure that the data entered was as accurate as possible, or
something like that;
sub is_decimal {
my $value = as_string( shift );
return ( $value =~ m,^[-+]?(\d+)?\.\d+$, ) ? 1 : 0;
}
>> round( $value ) - Rounds a number to the nearest integer.
> int($value + 0.5) is usually good enough.
Yeah, excapt when do want to round negative numbers as well;
return ( $value > 0 ) ? int($value + 0.5) : int($value - 0.5);
>> random_number( $min, $max ) - Returns a random number in the range
>> $min to $max.
> (rand * ($max - $min)) + $min
Right, but what if only one of $min or $max is known?
>> format_number( $value, $separator ) - Formats a number with a given
>> separator; 1234 becomes 1,234.
> Less trivial... is probably better done by something locale-aware.
Who says that a 'Utils' module can't be locale-aware? :)
>> unique( $arrayref ) - Returns only the unique elements in $array.
>> intersection( $arrayref1, $arrayref2 ) - Computes the intersection
>> of two array references.
>> union( $arrayref1, $arrayref2 ) - Computes the union of two array
>> references.
> These should all be in a module called Set::Util... feel free to write
> it.
It isn't in a module already? Doesn't it fit into List::Util?
-- Tore Aursand <tore@aursand.no> "Scientists are complaining that the new "Dinosaur" movie shows dinosaurs with lemurs, who didn't evolve for another million years. They're afraid the movie will give kids a mistaken impression. What about the fact that the dinosaurs are singing and dancing?" -- Jay Leno
- Next message: Jeff 'japhy' Pinyan: "Re: Using Tie::IxHash order a hash reference"
- Previous message: gibbering poster: "TK Help with Canvas"
- In reply to: Ben Morrow: "Re: RFC: utils.pm"
- Next in thread: Uri Guttman: "Re: RFC: utils.pm"
- Reply: Uri Guttman: "Re: RFC: utils.pm"
- Reply: Ben Morrow: "Re: RFC: utils.pm"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|