This module allows you to turn hashrefs into objects, so that instead of "$hash->{key}" you can write
"$hash->key", plus you get protection from typos. In addition, options are provided that allow you to
whip up really simple classes.
You can still use the hash like a normal hashref as well, as in "$hash->{key}", "keys %$hash", and so on,
but note that by default this function also locks the hash's keyset to prevent typos there too.
This module exports a single function by default.
"h2o@opts,$hashref,@additional_keys"@opts
If you specify an option with a value multiple times, only the last one will take effect.
"-recurse"
Nested hashes are objectified as well. The only options that are passed down to nested hashes are
"-lock" and "-ro". None of the other options will be applied to the nested hashes, including
@additional_keys. Nested arrayrefs are not recursed into, but see the "-arrays" option for that.
Versions of this module before v0.12 did not pass down the "-lock" option, meaning that if you used
"-nolock, -recurse" on those versions, the nested hashes would still be locked.
"-arrays"
Like "-recurse", but additionally, "h2o" is applied to elements of nested arrays as well. The same
options as with "-recurse" are passed down to nested hashes and arrayrefs. Takes precedence over the
"-pass" option, i.e. if you use these two options together, arrayrefs are still descended into. Like
hashrefs, the original arrays are modified!
This option implies "-recurse". This option was added in v0.20.
"-meth"
Any code references present in the hash at the time of this function call will be turned into
methods. Because these methods are installed into the object's package, they can't be changed later
by modifying the hash.
To avoid confusion when iterating over the hash, the hash entries that were turned into methods are
removed from the hash. The key is also removed from the "allowed keys" (see the "-lock" option),
unless you specify it in @additional_keys. In that case, you can change the value of that key
completely independently of the method with the same name.
"-class => classname"
Specify the class name into which to bless the object (as opposed to the default: a generated, unique
package name in "Util::H2O::").
Note: If you use this option, "-clean" defaults to false, meaning that the package will stay in
Perl's symbol table and use memory accordingly, and since this function installs the accessors in the
package every time it is called, if you re-use the same package name, you will get "redefined"
warnings. Therefore, if you want to create multiple objects in the same package, you should probably
use "-new" or "-classify".
If you wanted to generate a unique package name in a different package, you could use: "h2o -class =>
sprintf('My::Class::Name::_%x', $hash+0), $hash", perhaps even in combination with "-isa =>
'My::Class::Name'". However, keep in mind that you shouldn't step into another class' namespace
without knowing that this won't cause conflicts, and also that not using the default class names
means that functions like "o2h" will no longer identify the objects as coming from "h2o".
"-classify => classname_stringor$hashref"
In the form "-classify => classname_string", this is simply the short form of the options "-new,
-meth, -class => classname_string".
As of v0.16, in the special form "-classify => $hashref", where the "-classify" must be the last
option in @opts before the $hashref, it is the same as "-new, -meth, -class => __PACKAGE__, $hashref"
- that is, the current package's name is used as the custom class name. It does not make sense to use
this outside of an explicit package, since your class will be named "main". With this option, the
"Point" example in the "Synopsis" can be written like the following, which can be useful if you want
to add more things to the "package", or perhaps if you want to write your methods as regular "sub"s:
{
package Point;
use Util::H2O;
h2o -classify, {
angle => sub { my $self = shift; atan2($self->y, $self->x) }
}, qw/ x y /;
}
Note "h2o" will remain in the package's namespace, one possibility is that you could load
namespace::clean after you load this module.
You might also note that in the above example, one could write "angle" as a regular "sub" in the
package. And at that point, one might recongize the similarity between the code and what one can do
with e.g. Class::Tiny or even Moo.
"-isa => arrayreforscalar"
Convenience option to set the @ISA variable in the package of the object, so that the object inherits
from that/those package(s). This option was added in v0.14.
Warning: The methods created by "h2o" will not call superclass methods. This means the parent class'
"DESTROY" method(s) are not called, and any accessors generated from hash keys are blindly overriden.
"-new"
Generates a constructor named "new" in the package. The constructor works as a class and instance
method, and dies if it is given any arguments that it doesn't know about. If you want more advanced
features, like required arguments, validation, or other initialization, you should probably switch to
something like Moo instead.
"-destroy => coderef"
Allows you to specify a custom destructor. This coderef will be called from the object's actual
"DESTROY" in void context with the first argument being the same as the first argument to the
"DESTROY" method. Errors will be converted to warnings. This option was added in v0.14.
"-clean => bool"
Whether or not to clean up the generated package when the object is destroyed. Defaults to false when
"-class" is specified, true otherwise. If this is false, be aware that the packages will stay in
Perl's symbol table and use memory accordingly, and any subs/methods in those packages may cause
"redefined" warnings if the package name is re-used.
As of v0.16, this module will refuse to delete the package if it is named "main".
"-lock => bool"
Whether or not to use Hash::Util's "lock_ref_keys" to prevent modifications to the hash's keyset.
Defaults to true. The "-nolock" option is provided as a short form of "-lock=>0".
Keysets of objects created by the constructor generated by the "-new" option are also locked.
Versions of this module before v0.12 did not lock the keysets of new objects.
Note that on really old Perls, that is, before Perl v5.8.9, Hash::Util and its "lock_ref_keys" are
not available, so the hash is never locked on those versions of Perl. Versions of this module before
v0.06 did not lock the keyset. Versions of this module as of v0.12 issue a warning on old Perls.
"-nolock"
Short form of the option "-lock=>0".
"-ro"
Makes the entire hash read-only using Hash::Util's "lock_hashref" and the generated accessors will
also throw an error if you try to change values. In other words, this makes the object and the
underlying hash immutable.
You cannot specify any @additional_keys with this option enabled unless you also use the "-new"
option - the additional keys will then only be useful as arguments to the constructor. This option
can't be used with "-nolock" or "-lock=>0".
This option was added in v0.12. Using this option will not work and cause a warning when used on
really old Perls (before v5.8.9), because this functionality was not yet available there.
"-pass => "ref" or "undef""
When this option is set to "undef" (that's the string "undef", not "undef" itself!), then passing a
value of "undef" for the $hashref will not result in a fatal error, the value will simply be passed
through.
When this option is set to the string "ref", then any value other than a plain hashref that is a
reference, including objects, plus "undef" as above, will be passed through without modification. Any
hashes nested inside of these references will not be descended into, even when "-recurse" is
specified. However, "-arrays" takes precedence over this option, see its documentation.
This option was added in v0.18.
$hashref
You must supply a plain (unblessed) hash reference here, unless you've specified the "-pass" and/or
"-arrays" options. Be aware that this function does modify the original hashref(s) by blessing it and
locking its keyset (the latter can be disabled with the "-lock" option), and if you use "-meth" or
"-classify", keys whose values are code references will be removed. If you use "-arrays", the elements
of those arrays may also be modified.
An accessor will be set up for each key in the hash(es); note that the keys must of course be valid Perl
identifiers for you to be able to call the method normally (see also the "Cookbook").
The following keys will be treated specially by this module. Please note that there are further keys that
are treated specially by Perl and/or that other code may expect to be special, such as UNIVERSAL's "isa".
See also perlsub and the references therein.
"new"
This key is not allowed in the hash if the "-new" option is on.
"DESTROY"
This key is not allowed except if all of the following apply:
• "-destroy" is not used,
• "-clean" is off (which happens by default when you use "-class"),
• "-meth" is on, and
• the value of the key "DESTROY" is a coderef.
Versions of this module before v0.14 allowed a "DESTROY" key in more circumstances (whenever "-clean"
was off).
"AUTOLOAD"
If your hash contains a key named "AUTOLOAD", or this key is present in @additional_keys, this module
will set up a method called "AUTOLOAD", which is subject to Perl's normal autoloading behavior - see
"Autoloading" in perlsub and "AUTOLOAD" in perlobj. Without the "-meth" option, you will get a
"catch-all" accessor to which all method calls to unknown method names will go, and with "-meth"
enabled (which is implied by "-classify"), you can install your own custom "AUTOLOAD" handler by
passing a coderef as the value for this key - see "An Autoloading Example". However, it is important
to note that enabling autoloading removes any typo protection on method names!
@additional_keys
Methods will be set up for these keys even if they do not exist in the hash.
Please see the list of keys that are treated specially above.
Returns
The (now blessed and optionally locked) $hashref.
"o2h@opts,$h2object"
This function takes an object as created by "h2o" and turns it back into a hashref by making shallow
copies of the object hash and any nested objects that may have been created via "-recurse", "-arrays", or
created manually. This function is recursive by default because for a non-recursive operation you can
simply write: "{%$h2object}" (making a shallow copy).
Unlike "h2o", this function returns a new hashref instead of modifying the given variable in place
(unless what you give this function is not an "h2o" object, in which case it will just be returned
unchanged). Similarly, if you specify the "-arrays" option, shallow copies of arrays will be returned in
place of the original ones, with "o2h" applied to the elements.
Note that this function operates only on objects in the default package - it does not step into plain
hashrefs, it does not step into arrayrefs unless you specify "-arrays", nor does it operate on objects
created with the "-class" or "-classify" options. Also be aware that because methods created via "-meth"
are removed from the object hash, these will disappear in the resulting hashref.
This function was added in v0.18.
@opts
If you specify an option with a value multiple times, only the last one will take effect.
"-arrays"
If you specify this option, nested arrayrefs are descended into as well.
This option was added in v0.20.
"--"
This string ends the option processing, allowing you to pass scalar values to "o2h" that would
otherwise be interpreted as options.
The "o2h" function is special-cased such that a call "o2h("--")" returns "--" instead of throwing an
error.
This was added in v0.24 in order to fix a bug with scalars beginning with "-" in earlier versions of
this module. Users of "o2h" are advised to upgrade.