NAME
    Object::Adhoc - make objects without the hassle of defining a class first

SYNOPSIS
     use Object::Adhoc;
 
     my $object = object { name => 'Alice' };
 
     if ($object->has_name) {
       print $object->name, "\n";
     }

DESCRIPTION
    Object::Adhoc is designed to be an alternative to returning hashrefs from
    functions and methods. It's similar to Object::Anon but doesn't do
    anything special with references or overloading.

  Functions
    `object(\%data, \@keys)`
        Returns a blessed object built from the given arrayref.

        For each key in the list of keys, a getter (`name` in the SYNOPSIS)
        and predicate (`has_name` in the SYNOPSIS) method are created.

        Objects are read-only.

        Note that Object::Adhoc does not make a clone of %data before blessing
        it; it is blessed directly.

    object(\%data)
        If @keys is not supplied, Object::Adhoc will do this:

          @keys = keys(%data);

        If there are some keys that will not always be present in your data,
        passing Object::Adhoc a full list of every possible key is strongly
        recommended!

    `object(\%data, %opts)`
        The following options are supported:

        `recurse`
            Number of levels to recurse. By default, 0.

        `keys`
            `object(\%data, \@keys)` is a shortcut for `object(\%data, keys =>
            \@keys)`.

            When `keys` and `recurse` are both used, `keys` only applies to
            the root hashref.

    `make_class(\@keys, %opts)`
        Just makes the class, but doesn't bless a hashref into it. Returns a
        string which is the name of the class. If called repeatedly with the
        same keys, will return the same class name.

        By default, the class won't have a `new` method; if you need to create
        objects, you can just directly bless hashrefs into it.

          my $k = make_class( 'foo', 'bar' );
          my $o = bless { foo => 'Hello', bar => 'World' }, $k;
          if ( $o->isa($k) ) {
            say $o->foo, q( ), $o->bar;
          }

        Supported options:

        `ctor`
            Whether to create a constructor called `new`. Defaults to false.

        It is possible to use this in an @ISA, though that's not really the
        intention of Object::Adhoc.

          package My::Class {
            use Object::Adhoc 'make_class';
            our @ISA = make_class [qw/ foo bar baz /], ctor => 1;
            sub foobar {
              my ($self) = (shift);
              $self->foo . $self->bar;
            }
          }
  
          say My::Class->new( foo => "Hello", bar => "World" )->foobar;

        `make_class` is not exported by default.

  Diagnostics
   Ambiguous method '%s' is getter, not predicate
    Given the following:

      my $object = object {
        name     => 'Alice',
        has_name => 1,
      };

    Object::Adhoc doesn't know if you want the `has_name` method to be a
    getter for the "has_name" attribute, or a predicate for the "name"
    attribute. The getter wins, but it will issue a warning.

   Key '%s' would be bad method name, not generating methods
    You've got a key with a name that cannot be called as a method. For
    example:

      my $alice = object { 'given name' => 'Alice' };

    Perl methods cannot contain spaces, so Object::Adhoc refuses to create the
    method and gives you a warning. (Technically it is possible to create and
    call methods containing spaces, but it's fiddly.)

    This also happens for a few reserved method names like `AUTOLOAD`,
    `DESTROY`, `isa`, `DOES`, `can`, etc. These have particular meanings in
    Perl that would conflict with them being used as a getter method.

   Bad recurse option
    The `recurse` option must be a positive integer or zero.

   Usage %s(self)
    The methods defined by Object::Adhoc expect to be invoked with a blessed
    object and no other parameters.

      my $alice = object { 'name' => 'Alice' };
      $alice->name(1234);   # error

    This throws an exception rather than just printing a warning.

   Usage %s(class, hashref)
    The constructor created by the `ctor` option was called with bad
    parameters.

   Bad key: %s
    The constructor created by the `ctor` option was called with an unknown
    key.

BUGS
    Please report any bugs to
    <https://github.com/tobyink/p5-object-adhoc/issues>.

SEE ALSO
  Comparison with Similar Modules
    Object::Adhoc - requires Exporter::Tiny and uses Class::XSAccessor if
    installed; read-only accessors; predicate methods; optional recursion into
    nested hashrefs, arrayrefs, scalarrefs, and coderefs; no overloading; dies
    on unknown keys.

    Object::Anon only core dependencies; read-only accessors; no predicate
    methods; recuses into nested hashrefs and arrayrefs; treats coderef values
    as methods and supports overloading; dies on unknown keys.

    Hash::Objectify - requires Class::XSAccessor; read-write accessors; no
    predicate methods; no recursion; no overloading; dies on unknown keys (or
    returns undef in lax mode).

    Hash::AsObject - only core dependencies; read-write accessors (uses
    AUTOLOAD, potentially slow); no predicate methods; recurses into nested
    hashrefs; no overloading; returns undef for unknown keys.

    Of the four, Object::Adhoc has the fastest accessors, and Hash::Objectify
    has the fastest constructors. Object::Anon is the slowest.

    I'd recommend Object::Adhoc if you want read-only accessors, or
    Hash::Objectify if you want read-write accessors. Use Object::Anon only if
    you need the additional features it supports like overloading and custom
    methods.

  Not Quite So Similar Modules
    Object::Result - fairly different idea, but can be used for similar
    purposes. Requires Perl 5.14, Keyword::Simple, PPI, and
    Method::Signatures.

AUTHOR
    Toby Inkster <tobyink@cpan.org>.

COPYRIGHT AND LICENCE
    This software is copyright (c) 2020-2022, 2025 by Toby Inkster.

    This is free software; you can redistribute it and/or modify it under the
    same terms as the Perl 5 programming language system itself.

DISCLAIMER OF WARRANTIES
    THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
    WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
    MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

