Acme::Util - Frequently Hacked Functions
A cookbook of tasty functions for the terminally lazy, impatient and hubristic
Rather than listing a group of functions by name, related subs can be imported using the tag syntax:
use Acme::Util qw(:tag);
The following tags have been defined:
:io
appendfile, atime, ctime, mtime, reader, readfile, writefile
:www
html, js, text, xml, xmlparse
:text
capitalize, commify, csv, ltrim, plural, rtrim, trim
:misc
any, apply, arrayref, coderef, find, hashref, scalarref, clone, id, respond, swap
:math
div, inf, infinity, isbig, isfloat, isinf, isnan, isneg, isnum, isuv
# return 0 or 1 my $flip = any(); # return a random element of the ARRAY or a random HASH key my $el = any($hash_or_array_ref); # return a randomly selected list of ARRAY elements / HASH keys my @els = any($hash_or_array_ref, $number_of_items_to_pick); # as above, but return the elements as an ARRAY ref (if # $number_of_items_to_pick is greater than 1) my $els = any($hash_or_array_ref, $number_of_items_to_pick); # allow the same element to be picked multiple times my @els = any($hash_or_array_ref, $number_of_items_to_pick, $with_replacement); my $els = any($hash_or_array_ref, $number_of_items_to_pick, $with_replacement); # return a random number between 0 and $integer_max inclusive my $int = any($integer_max); # return a random number between $integer_min and $integer_max # inclusive my $int = any($integer_min, $integer_max);
Returns a randomly chosen member of the referenced ARRAY, or a random key from the referenced HASH.
If the second argument is supplied, that number of items is chosen and returned as a list - defaults to 1.
If the third argument is supplied, items can be repeatedly chosen - defaults to 0 (false).
If the first argument is an integer x, an integer between 0 and x (inclusive) is returned.
If no argument is supplied, 0 or 1 is returned randomly.
If the first and second arguments are integers x and y, then an integer between x and y (inclusive) is returned.
any($ref, ...) does not modify the original HASH/ARRAY. any($ref, $reflength) returns a shuffled list e.g. # perform a non-destructive shuffle of the elements of $array my @shuffled = any($array, $#$array + 1)
When supplied with a HASH or ARRAY ref, and a second argument (specifying the number of items to pick) greater than 1, the selected values are returned as a list in list context and an ARRAY ref in scalar context.
appendfile($file, $data, %args);
This is a simple wrapper for writefile()'s APPEND option.
Appends $data to the file whose path is specified by $file.
See writefile() for %args options.
my $result = apply $coderef, @optional_args; # or my $result = apply sub { do_something() }, @optional_args; # or my $result = apply \&Name::Space::sub, @optional_args;
Invokes the subroutine supplied as the first argument, passing any arguments in @optional_args as parameters.
Returns the result of the subroutine call.
do_something() if (arrayref $arg);
Returns a true value if $arg is a blessed or unblessed ARRAY reference.
Returns a false value otherwise.
my $atime = atime($file);
Returns the time (in seconds since the epoch) the specified file was last accessed.
my $capitalized = capitalize($string); # or my $capitalized = capitalize($string, @do_not_capitalize_these_words);
Initial-capitalizes $string i.e. any words (defined as consecutive characters between word-boundaries (\b)) in $string that don't already contain capitals are lowercased and their initials are uppercased.
Note: apostrophes are treated as word characters, so:
"There's more than one way to do it"
becomes:
"There's More Than One Way To Do It"
rather than:
"There'S More Than One Way To Do It"
Any arguments supplied after $string are treated as exceptions and left as is.
For non-trivial capitalization see the { case => 'highlight' } option of Damian Conway's Text::Autoformat.
In the absence of an explicit exception list, Acme::Util's capitalize() (and Text::Autoformat's { case => 'title' }) mechanically renders the text:
'what i did on my summer vacation in monterey'
as:
'What I Did On My Summer Vacation In Monterey'
Whereas Text::Autoformat's { case => 'highlight' } option offers the much more titular:
'What I Did on my Summer Vacation in Monterey'
use Acme::Util qw(clone); $a = Foo->new(); $b = { alpha => 'beta', gamma => 'vlissides' }; tie %c, 'Foo::Bar'; $d = clone($a); $e = clone($b); $f = clone(\%c); # or my $node2 = { name => 'node2', children => [ $node3, $node4 ], parent => weaken ($node1) # weaken() to avoid memory leak }; # clone $node2 but preserve the original $node1 (rather than cloning # through it all the way to the root) my $clone = clone($node2, [ $node1 ]); # or, equivalently my $clone = clone($node2, [ $node2->{parent} ]);
clone() returns a recursive copy of its argument, which can be an arbitrary (scalar) type including nested HASH, ARRAY and reference types (including weak references), tied variables and objects.
To duplicate non-scalar types (e.g. lists, ARRAYs and HASHes), pass them to clone() by reference. e.g.
my $copy = clone (\@array); # or my %copy = %{ clone (\%hash) };
clone() takes an optional second argument: a reference to an ARRAY containing a list of exceptions i.e. values that should be 'passed-thru' verbatim. This is useful for, amongst other things, cloning nodes in a hierarchy without duplicating the structure all the way to the root.
For a slower, but more flexible solution see Storable's dclone().
do_something() if (coderef $arg);
Returns a true value if $arg is a blessed or unblessed CODE reference.
my $pretty = commify($int);
Returns a reader-friendly representation of the supplied integer punctuated with commas at the customary thousands/millions (&c.) points.
Thus:
printf "%-9u\t%11s%s", $_, commify($_), $/ for (map { $_ x $_ } 1 .. 9);
prints:
1 1 22 22 333 333 4444 4,444 55555 55,555 666666 666,666 7777777 7,777,777 88888888 88,888,888 999999999 999,999,999
my $csv = csv($fields, $arrayref); # or my $csv = csv [ 'alpha', 'beta', 'gamma', 'vlissides' ], [ { alpha => 'fee', beta => 'fie', gamma => 'foe', vlissides => 'fum' }, { alpha => 'foo', beta => 'bar', gamma => 'baz', vlissides => 'foobar' }, { alpha => 'one', beta => 'two', gamma => 'three', vlissides => 'four' } ]; # or my $csv = csv [ 'alpha', 'beta', 'gamma', 'vlissides' ], [ [ qw(fee fie foe fum) ], [ qw(foo bar baz foobar) ], [ qw(one two three four) ], ]; # yields "alpha","beta","gamma","delta" "fee","fie","foe","fum" "foo","bar","baz","foobar" "one","two","three","four"
$fields: an ARRAY ref representing a list of field names $arrayref: a reference to an ARRAY of HASH or ARRAY references
Returns either a string or (in list context) a list representing the rows of a CSV (Comma Separated Values) document generated from the supplied HASH or ARRAY refs and using the fields listed in $fields as the field names.
Field names and values are double quoted.
my $ctime = ctime($file);
Returns the time (in seconds since the epoch) the specified file was created.
my ($quotient, $remainder) = div ($numerator, $denominator); # e.g. my ($q, $r) = div (13, 3); # $q = 4, $r = 1: # 13 ($numerator) = 4 ($quotient) x 3 ($denominator) + 1 ($remainder)
Integer division operator: in list context, returns the quotient and remainder when the first operand ($numerator) is divided by the second ($denominator).
i.e.
$numerator = $quotient * $denominator + $remainder
In scalar context, returns just the quotient. To return the remainder, use %.
my $index = find ($arrayref, $scalar) # or my $index = find ($arrayref, $scalar, $from)
Returns the offset of $scalar within $arrayref, with the first position denoted by 0.
$scalar can be a number, string or reference.
-1 is returned if the item is not found.
If the third argument is supplied, the search begins at that index (the offset is still calculated from the beginning of the ARRAY ref).
do_something() if (hashref $arg);
Returns a true value if $arg is a blessed or unblessed HASH reference.
html ($text); # or html ();
Returns $text with the 'text/html' Content-type header prefixed; or just the header if no $text is provided.
Prints the prefixed page out directly if called in void context.
id()
Returns a quick 'n' dirty Unique Identifier. Uses $$ (amongst other things), so not necessarily reliable under SpeedyCGI, mod_perl &c.
my $inf = infinity() # or my $inf = inf()
Perl 5.8 claims to support infinity natively, but falls short on many platforms. This utility function is a trivial wrapper for the Swiss-Army $Inf provided by Math::Complex, which jumps through every possible hoop to deliver a high-quality infinity product for your reckoning pleasure.
isnum ($val)
Returns a nonzero value (indicating the numeric type) if $val is a number.
The numeric types are a conjunction of the following flags:
0x01 IS_NUMBER_IN_UV (number within UV range - maybe not int) 0x02 IS_NUMBER_GREATER_THAN_UV_MAX (the pointed-to UV is undefined) 0x04 IS_NUMBER_NOT_INT (saw . or E notation) 0x08 IS_NUMBER_NEG (leading minus sign) 0x10 IS_NUMBER_INFINITY (this is big) 0x20 IS_NUMBER_NAN (this is not)
Rather than obliging the user to twiddle with bits, the following flavours of isnum (corresponding to the flags above) are also available:
isint isuv isbig isfloat isneg isinf isnan
isint returns -1 if its operand is a negative integer, 1 if it's 0 or a positive integer, and 0 otherwise.
The others always return 1 or 0.
js ($text); # or js ();
Returns the JavaScript in $text with the 'application/x-javascript' Content-type header prefixed; or just the header if no $text is provided.
Prints the prefixed page out directly if called in void context
my $trimmed = ltrim ($string);
Returns a copy of $string with whitespace removed from the beginning.
my $mtime = mtime($file);
Returns the time (in seconds since the epoch) the specified file was last modified.
my $plural = plural($stem, $count); # or my $plural = plural($stem, $count, $plural);
Plural() takes a singular word or word-stem as an argument; it evaluates $count to see if it is equal to 1; if it is, $stem is returned unchanged; otherwise $stem is pluralised by adding $plural, or 's' if $plural hasn't been supplied.
my $plural = plural('error', $error); will return: 'errors' if $error == 0 'error' if $error == 1 'errors' if $error > 1
This simple implementation does not support irregular plurals that modify the stem. For solutions to that, and indeed, most other non-trivial pluralization problems, the reader is referred to Damian Conway's Lingua::EN::Inflect.
my $source = ''; my $read = reader($path, IRS => '...', CHOMP => 1); while ($read->(\$source)) { do_something_with($source); } # or while ($read->()) { # implied target: $_ do_something_with($_); }
This method implements a generator/continuation interface to the fine art of file slurpage. It provides a private (lexically scoped) filehandle and an associated file reader (in the form of a closure).
This closure should be called with a reference to the variable one wishes to be assigned the next line from the file.
If no argument is supplied then $_ is assumed to be the target.
The generator yields true while the file is slurping, and undef thereafter.
The file is automatically closed either when the file has been read, or the closure goes out of scope - whichever comes first.
Swiss-Army Slurp
# vanilla readfile $path; # print the file # or my $file = readfile $path; # handle warnings/fatal errors my $file = readfile $path, WARN => \&my_warn, DIE => sub { die @_ }; # lines my @file = readfile $path; # set Input Record Separator my @file = readfile $path, IRS => '...'; # strip Input Record Separator from result my @file = readfile $path, IRS => '...', CHOMP => 1; # open a binary file (e.g. on Windows/Cygwin) my $file = readfile $path, BINARY => 1; # all together now... my $file = readfile ( $path, WARN => $warn, DIE => $die, IRS => '...', BINARY => 1, CHOMP => 1); # synonyms for IRS => DELIM, SPLIT, DELIMITER # synonym for BINARY => BINMODE
respond ($scalar) respond (@list)
respond() performs a context-sensitive return:
In void context the supplied arguments are printed. In scalar context it returns: the supplied argument if there's only one the concatenation of its arguments if there's more than one In list context it returns the arguments unchanged.
my $trimmed = rtrim ($string);
Returns a copy of $string with whitespace removed from the end.
do_something() if (scalarref $arg);
Returns a true value if $arg is a blessed or unblessed SCALAR reference.
my $text = squash ($string);
Returns a 'flat' copy of $string i.e. with initial and terminal whitespace removed and one or more internal whitespace characters (including carriage-returns and newlines) squashed into a single space.
swap($x, $y);
Sets the value of $x to $y and vice-versa.
swap() is prototyped to receive its arguments by reference, and modifies its arguments in place like chop, chomp &c.
No value is returned
text ($text); # or text ();
Returns $text with the 'text/plain' Content-type header prefixed; or just the header if no $text is provided.
my $trimmed = trim ($string);
Returns a copy of $string with whitespace removed from the beginning and end; in addition, consecutive internal spaces are squashed to a single space.
my $url = urlize('Foo: BAR baz'); # returns 'foo_bar_baz' # or my $url = urlize('Foo - BAR - baz', 'html'); # returns 'foo_bar_baz.html'
Makes its text argument URL-friendly.
Returns the first argument lowercased with any consecutive non-alphanumeric characters replaced by an underscore.
If the optional second argument is provided, this is appended as an extension prefixed by '.'
writefile($file, $data, %args);
Write $data to filename $file. Additional herbs and spices are specified as a list of pairs, in the same manner as readfile (and reader).
Currently, the following options are supported:
APPEND => 1 for append (as opposed to truncate) MODE => $mode (to roll your own file access mode) BINARY/BINMODE => 1 to write a binary file (e.g. on Windows/Cygwin)
xml ($text); # or xml ();
Returns (optional) $text with the 'text/xml' Content-type header prefixed; or just the header if no $text is provided.
xmlparse ($parser, $xml_path_or_data);
Convenience wrapper for XML::Parser (or XML::Parser::Expat - or indeed any parser that supports parse() and parsefile()) that is agnostic with regard to whether $xml is a file/filehandle or raw XML text.
The $parser should be prefabricated according to taste.
clone() currently segfaults if it encounters a Regex object
Scalar::Util, List::Util, Clone, Storable, File::Butler, Toolbox
chocolateboy: <chocolate.boy@email.com>
Copyright (c) 2001-2004, chocolateboy.
This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.
To install Acme::Util, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Acme::Util
CPAN shell
perl -MCPAN -e shell install Acme::Util
For more information on module installation, please visit the detailed CPAN module installation guide.