List::...::Hash(3pm)

πŸ“¦
version 2.028003 Β· 4 versions
, in debian trixie, ubuntu resolute, ubuntu stonking

🌸 List::Objects::WithUtils::Role::Hash β€” Hash manipulation methods 🌸

okay bestie, buckle UP β€” this is List::...::Hash(3pm) from the User Contributed Perl Documentation, and it's genuinely one of my faves. It's the page for List::Objects::WithUtils::Role::Hash, a role that hands you a whole lil toolbox for hash-type objects. Let's get into it πŸ’–


✨ NAME ✨

List::Objects::WithUtils::Role::Hash β€” Hash manipulation methods. That's it, that's the name, slay.


πŸ¦‹ SYNOPSIS πŸ¦‹

Here's the vibe, in code, no cap:

## Via List::Objects::WithUtils::Hash ->
use List::Objects::WithUtils 'hash';

my $hash = hash(foo => 'bar');

$hash->set(
  foo => 'baz',
  pie => 'tasty',
);

my @matches = $hash->keys->grep(sub { $_[0] =~ /foo/ })->all;

my $pie = $hash->get('pie')
  if $hash->exists('pie');

for my $pair ( $hash->kv->all ) {
  my ($key, $val) = @$pair;
  ...
}

my $obj = $hash->inflate;
my $foo = $obj->foo;

## As a Role ->
use Role::Tiny::With;
with 'List::Objects::WithUtils::Role::Hash';

πŸ’… DESCRIPTION πŸ’…

So this is a Role::Tiny role, and what it does is define all the methods you need for creating and manipulating HASH-type objects. It's giving ✨infrastructure✨.

On top of the methods documented down below, these objects also come with a TO_JSON method that exports a plain HASH-type reference β€” super handy when you're feeding JSON::Tiny or something similar β€” plus a TO_ZPL method for compatibility with Text::ZPL. Convenient? Yes. Iconic? Also yes.


πŸŽ€ Basic hash methods πŸŽ€

new

Constructs a new HASH-type object. Fresh out the box, literally brand new ✨

copy

Creates a shallow clone of the current object. Shallow, bestie, not a deep clone β€” don't get it twisted.

defined

if ( $hash->defined($key) ) { ... }

Returns boolean true if the key has a defined value. πŸ’―

exists

if ( $hash->exists($key) ) { ... }

Returns boolean true if the key exists. (Yes, exists and defined are different things β€” main character energy of Perl, honestly.)

export

my %hash = $hash->export;

Returns a raw key => value list. Raw, unfiltered, no makeup.

For a plain HASH-type reference instead, go see: "unbless".

array_type

The class name of the array-type objects that get used to contain the results of methods returning a list.

Defaults to List::Objects::WithUtils::Array.

Subclasses can override array_type to produce different types of array objects. Customize your own destiny, fr fr πŸ’…

inflate

my $obj = hash(foo => 'bar', baz => 'quux')->inflate;
my $baz = $obj->baz;

Inflates the hash-type object into a simple struct-like object with accessor methods matching the keys of the hash. It's giving glow-up 🌈

By default, accessors are read-only; specifying rw => 1 allows setting new values:

my $obj = hash(foo => 'bar', baz => 'quux')->inflate(rw => 1);
$obj->foo('frobulate');

Returns an inflated_type (or inflated_rw_type) object.

The default objects provide a DEFLATE method returning a plain hash; this makes it easy to turn inflated objects back into a hash() for modification:

my $first = hash( foo => 'bar', baz => 'quux' )->inflate;
my $second = hash( $first->DEFLATE, frobulate => 1 )->inflate;

inflated_type

The class that objects are blessed into when calling "inflate".

Defaults to List::Objects::WithUtils::Hash::Inflated.

inflated_rw_type

The class that objects are blessed into when calling "inflate" with rw => 1 specified.

Defaults to List::Objects::WithUtils::Hash::Inflated::RW, a subclass of List::Objects::WithUtils::Hash::Inflated.

is_empty

Returns boolean true if the hash has no keys. Empty hash = empty vibes πŸ«™

is_mutable

Returns boolean true if the hash is mutable; immutable subclasses can override to provide a negative value.

is_immutable

The opposite of "is_mutable". Simple as that πŸ’

unbless

Returns a plain HASH reference (shallow clone).


πŸ”₯ Methods that manipulate the hash πŸ”₯

clear

Clears the current hash entirely. Wipes it. Gone. πŸ’€

Returns the (same, but now empty) hash object.

delete

$hash->delete(@keys);

Deletes the given key(s) from the hash.

Returns an array_type object containing the deleted values.

set

$hash->set(
  key1 => $val,
  key2 => $other,
)

Sets keys in the hash.

Returns the current hash object.

maybe_set

my $hash = hash(foo => 1, bar => 2, baz => 3);
$hash->maybe_set(foo => 2, bar => 3, quux => 4);
# $hash = +{ foo => 1, bar => 2, baz => 3, quux => 4 }

Like "set", but only sets values that do not already exist in the hash. Respectful. Knows when to back off. 🫢

Returns the current hash object.


πŸ’œ Methods that retrieve items πŸ’œ

get

my $val  = $hash->get($key);
my @vals = $hash->get(@keys)->all;

Retrieves a key or list of keys from the hash.

If you're taking a slice (multiple keys were specified), values are returned as an array_type object. (See "sliced" if you'd rather generate a new hash.)

get_path

my $hash = hash(
  foo  => +{ bar => +{ baz => 'bork'  } },
  quux => [ +{ weeble => 'snork' } ],
);
my $item = $hash->get_path(qw/foo bar baz/);  # 'bork'

Attempt to retrieve a value from a 'deep' hash (without risking autovivification). No accidental creations, we're being careful 🧚

If an element of the given path is a (plain) array reference, as in this example:

my $item = $hash->get_path('quux', [1], 'weeble');  # "snork"

... then it is taken as the index of an array or array-type object in the path.

Returns undef if any of the path elements are nonexistant.

An exception is thrown if an invalid access is attempted, such as trying to use a hash-type object as if it were an array. So like, don't do that. 😭

(Available from v2.15.1)

get_or_else

# Expect to find an array() obj at $key in $hash,
# or create an empty one if $key doesn't exist:
my @all = $hash->get_or_else($key => array)->all;

# Or pass a coderef
# First arg is the object being operated on
# Second arg is the requested key
my $item = $hash->get_or_else($key => sub { shift->get($defaultkey) });

Retrieves a key from the hash; optionally takes a second argument that is used as a default value if the given key does not exist in the hash.

If the second argument is a coderef, it is invoked on the object (with the requested key as an argument) and its return value is taken as the default value. Fancy πŸ’…

keys

my @keys = $hash->keys->all;

Returns the list of keys in the hash as an array_type object.

values

my @vals = $hash->values->all;

Returns the list of values in the hash as an array_type object.

inverted

my $hash = hash(
  a => 1,
  b => 2,
  c => 2,
  d => 3
);
my $newhash = $hash->inverted;
# $newhash = +{
#   1 => array('a'),
#   2 => array('b', 'c'),
#   3 => array('d'),
# }

Inverts the hash; the values of the original hash become keys in the new object. Their corresponding values are array_type objects containing the key(s) that mapped to the original value.

This is a bit like reversing the hash, but lossless with regards to non-unique values. No data left behind, we don't do that here 🌸

(Available from v2.14.1)

iter

my $iter = $hash->iter;
while (my ($key, $val) = $iter->()) {
  # ...
}

Returns an iterator that, when called, returns ($key, $value) pairs. When the list is exhausted, an empty list is returned.

The iterator operates on a shallow clone of the hash, making it safe to operate on the original hash while using the iterator. Safety first, bestie 🫢

(Available from v2.9.1)

kv

for my $pair ($hash->kv->all) {
  my ($key, $val) = @$pair;
}

Returns an array_type object containing the key/value pairs in the hash, each of which is a two-element (unblessed) ARRAY.

kv_grep

my $positive_vals = $hash->kv_grep(sub { $b > 0 });

Like "grep", but operates on pairs. See "pairgrep" in List::Util.

Returns a hash-type object consisting of the key/value pairs for which the given block returned true.

(Available from v2.21.1)

kv_map

# Add 1 to each value, get back an array-type object:
my $kvs = hash(a => 2, b => 2, c => 3)
  ->kv_map(sub { ($a, $b + 1) });

Like "map", but operates on pairs. See "pairmap" in List::Util.

Returns an array_type object containing the results of the map.

(Available from v2.8.1; in versions prior to v2.20.1, $_[0] and $_[1] must be used in place of $a and $b, respectively.) ⚠️ old-version heads, this one's for you

kv_sort

my $kvs = hash(a => 1, b => 2, c => 3)->kv_sort;
# $kvs = array(
#          [ a => 1 ],
#          [ b => 2 ],
#          [ c => 3 ]
#        )

my $reversed = hash(a => 1, b => 2, c => 3)
  ->kv_sort(sub { $b cmp $a });
# Reverse result as above

Like "kv", but sorted by key. A sort routine can be provided.

In versions prior to v2.19.1, $_[0] and $_[1] must be used in place of $a and $b, respectively. same warning energy, different version number

random_kv

Returns a random key/value pair from the hash as an ARRAY-type reference. Spin the wheel 🎑

Returns undef if the hash is empty.

(Available from v2.28.1)

random_key

Returns a random key from the hash. Mystery key, cute ✨

Returns undef if the hash is empty.

(Available from v2.28.1)

random_value

Returns a random value from the hash.

Returns undef if the hash is empty.

(Available from v2.28.1)

sliced

my $newhash = $hash->sliced(@keys);

Returns a new hash object built from the specified set of keys and their respective values.

If a given key is not found in the hash, it is omitted from the result (this is different than "perl-5.20+" hash slice syntax, which sets unknown keys to undef in the slice). Subtle but important, iykyk πŸ‘‘

If you only need the values, see "get".


🌈 Methods that compare hashes 🌈

intersection

my $first  = hash(a => 1, b => 2, c => 3);
my $second = hash(b => 2, c => 3, d => 4);
my $intersection = $first->intersection($second);
my @common = $intersection->sort->all;

Returns the list of keys common between all given hash-type objects (including the invocant) as an array_type object. Finding your people, fr fr 🫢

diff

The opposite of "intersection"; returns the list of keys that are not common to all given hash-type objects (including the invocant) as an array_type object.


🧚 NOTES FOR CONSUMERS 🧚

If you're creating your own consumer of this role, some extra effort is required to make $a and $b work in sort statements without warnings; an example with a custom exported constructor might look something like:

package My::Custom::Hash;
use strictures 2;
require Role::Tiny;
Role::Tiny->apply_roles_to_package( __PACKAGE__,
  qw/
    List::Objects::WithUtils::Role::Hash
    My::Custom::Hash::Role
  /
);

use Exporter ();
our @EXPORT = 'myhash';
sub import {
  my $pkg = caller;
  { no strict 'refs';
    ${"${pkg}::a"} = ${"${pkg}::a"};
    ${"${pkg}::b"} = ${"${pkg}::b"};
  }
  goto &Exporter::import
}

sub myhash { __PACKAGE__->new(@_) }
Heads up bestie: that no strict 'refs' block is doing real work β€” it's how $a and $b get into your caller's namespace so sort blocks don't scream warnings at you. Don't skip it. πŸ™ˆ

πŸ‘‘ SEE ALSO πŸ‘‘

  • List::Objects::WithUtils
  • List::Objects::WithUtils::Hash
  • List::Objects::WithUtils::Hash::Immutable
  • List::Objects::WithUtils::Hash::Typed
  • Data::Perl

okay that's part one, there's MORE coming so don't go anywhere bestie πŸ’–

πŸ’– AUTHOR πŸ’–

Okay so who even made this masterpiece? Bestie, gather round:

  • Jon Portnoy β€” <avenj@cobaltirc.org> πŸ‘‘ (the main character who wrote this)
  • Some of this code is derived from Data::Perl by Matthew Phillips (CPAN: MATTP), haarg et al 🫢 β€” shoutout to the OGs, no cap
  • Licensed under the same terms as Perl 🌈 β€” so like, the license vibe is inherited, iconic behavior honestly

And that's the whole page, bestie!! πŸŽ€ You made it to the end, so proud of you fr fr. This little gem is from perl v5.38.2, dated 2024-03-07, and it's filed under List::...::Hash(3pm) β€” which, yes, is literally the name, we're not hiding anything πŸ’…

Now go forth and slay those lists into hashes. Mwah. πŸ’‹βœ¨

πŸ“¦ where this page comes from