The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

OOB - out of bounds data for any data structure in Perl

VERSION

This documentation describes version 0.03.

SYNOPSIS

 # object oriented interface
 use OOB;

 # register attributes
 OOB->ContentType;
 OOB->EpochStart;
 OOB->Currency;
 OOB->Accept;

 # scalars (or scalar refs)
 OOB->ContentType( $message, 'text/html' );
 my $type = OOB->ContentType($message);
 print <<"MAIL";
 Content-Type: $type

 $message
 MAIL

 # arrays
 OOB->EpochStart( \@years, 1970 );
 my $offset = OOB->EpochStart( \@years );
 print $offset + $_ , $/ foreach @years;

 # hashes
 OOB->Currency( \%salary, 'EUR' );
 my $currency = OOB->Currency( \%salary );
 print "$_: $salary{$_} $currency\n" foreach sort keys %salary;

 # subroutines
 OOB->Accept( \&frobnicate, \@classes );
 my $classes = OOB->Accept( \&frobnicate );

 # functional interface
 use OOB qw( OOB_set OOB_get OOB_reset );

 package Foo;
 OOB_set( $scalar, key => $value );
 my $value = OOB_get( @array, 'key' );
 OOB_reset( %hash );

 package Bar;
 my $value = OOB_get( $arrayref, 'key', 'Foo' ); # other module's namespace

DESCRIPTION

This module makes it possible to assign any out of bounds data (attributes) to any Perl data structure with both a functional and an object oriented interface. Out of bounds data is basically represented by a key / value pair.

Object Oriented Interface

The object oriented interface allows you to easily define globally accessible meta-data attributes. To prevent problems by poorly typed attribute names, you need to register a new attribute at least once before being able to set it. Attempting to access any non-existing meta-data attributes will not result in an error, but simply return undef.

Registration of an attribute is simple: just calling it as a class method on the OOB module is enough:

 use OOB;
 OOB->ContentType;

After that, you can use that attribute on any Perl data structure:

 OOB->ContentType( $string,  'text/html' ); # scalars don't need to be ref'ed
 OOB->ContentType( \$string, 'text/html' ); # same as above
 OOB->ContentType( \@array,  'text/html' );
 OOB->ContentType( \%hash,   'text/html' );
 OOB->ContentType( \&sub,    'text/html' );
 OOB->ContentType( *FILE,    'text/html' ); # globs
 OOB->ContentType( $handle,  'text/html' ); # blessed objects

Functional Interface

The functional interface gives more flexibility but may not be as easy to type. It basically allows you to specify arrays, hashes and subs directly (courtesy of Perl's prototyping feature). The functional interface is in principle limited to the namespace from which it is being called, but can be overridden if necessary.

 use OOB qw( OOB_set OOB_get OOB_reset ); # nothing exported by default

 package Foo;
 OOB_set( $string, ContentType => 'html' );
 my $type = OOB_get( $string, 'ContentType' );        # attribute in 'Foo'

 package Bar;
 my $type = OOB_get( $string, ContentType => 'Foo' ); # other namespace
 OOB_set( $string, ContentType => "text/$type" );     # attribute in "Bar"

 OOB_set( $string, ContentType => 'text/html' ); # equivalent to object
 OOB_set( @array,  ContentType => 'text/html' ); # oriented examples, but
 OOB_set( %hash,   ContentType => 'text/html' ); # limited to the current
 OOB_set( &sub,    ContentType => 'text/html' ); # namespace
 OOB_set( *FILE,   ContentType => 'text/html' );
 OOB_set( $handle, ContentType => 'text/html' );

THEORY OF OPERATION

The functional interface of the OOB pragma basically uses the refaddr of the given value as an internal key to create an "inside-out" hash ref with the given keys and values. If the value is not blessed yet, it will be blessed in the OOB class, so that it can perform cleanup operations once the value goes out of scope.

If a blessed value is specified, the DESTROY method of the class of the object is stolen, so that OOB can perform its cleanup after the original DESTROY method was called. This is only supported if the Sub::Identify module is also installed. If that module cannot be found, a warning will be issued once to indicate that no cleanup can be performed for blessed objects, and execution will then continue as normal.

To prevent clashes between different modules use of the out-of-bounds data, the package name of the caller is automatically added to any key specified, thereby giving each package its own namespace in the OOB environment. However, if need be, a module can access data from another package by the additional specification of its namespace.

The object oriented interface is really nothing more than synctactic sugar on top of the functional interface. The namespace that is being used by all of the attributes specified with the object oriented interface is the OOB package itself.

REQUIRED MODULES

 Scalar::Util (1.14)

AUTHOR

Elizabeth Mattijsen, <liz@dijkmat.nl>.

Please report bugs to <perlbugs@dijkmat.nl>.

ACKNOWLEDGEMENTS

Juerd Waalboer for the insight that you don't need to keep a reference on a blessed Perl data structure such as a scalar, array or hash, but instead can use any reference to that data structure to find out its blessedness.

COPYRIGHT

Copyright (c) 2008 Elizabeth Mattijsen <liz@dijkmat.nl>. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

SEE ALSO