The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Lexical::Hints - A featureful replacement for %^H

VERSION

This document describes Lexical::Hints version 0.000005

SYNOPSIS

    use Lexical::Hints;

    # Set a hint at compile-time...
    sub import {
        ...
        set_hint( $HINT_NAME => $HINT_VALUE );
        ...
    }

    # Retrieve a hint at runtime...
    sub runtime_sub {
        ...
        $hint_val = get_hint( $HINT_NAME );
        ...
    }

    # Dump all currently active hints...
    Lexical::Hints::dump();

DESCRIPTION

This module provides a cleaner interface to the built-in "lexical hints hash" (%^H), and adds some useful new features to the existing mechanism. See perlpragma for details of the standard lexical hinting API.

INTERFACE

Setting up lexical hints at compile-time

set_hint( $HINT_NAME, $HINT_VALUE, \%OPTIONS )

The set_hint() subroutine expects two or three arguments:

  • The name of the hint whose value is being set

  • The value of the hint whose value is being set

  • An optional reference to a hash containing named options

The subroutine does not return any useful value.

The name can be any string you choose. There is no need to follow the normal convention of prefixing the hint name with the current module name; set_hint() will take care of that automatically.

The value can be any valid scalar: a number, a string, any kind of reference, a qr, etc..

The only option currently offered is: { up => $UPSCOPE_COUNT }. In the absence of this option, the hint is set for the scope currently being compiled (at compile-time) or the lexical scope of the current subroutine's immediate caller (at runtime).

However if the option is included in a runtime call to set_hint(), then the hint is (re)set in the scope indicated. For example:

    set_hint('debugger' => $debug_sub_ref , { up => 2 });

sets the 'debugger' hint in the scope of the current subroutine's caller's caller's caller (i.e. in the scope that caller(2) would report on).

Setting lexical hints at runtime

Unlike %^H, which can only be assigned to at compile-time, set_hint() can be called at runtime as well. However, when called at runtime, only pre-existing hints (i.e. those previously created by a compile-time call to set_hint()) can be modified.

Note that any runtime changes to a lexical hint will persist for the rest of the program. Although the hints themselves are lexically scoped, changes to the hint values are not. That is, the hints of a particular lexical scope are like invisible state variables in that scope, not like invisible my variables.

Generally, it's best not to reset lexical hints at run-time, unless you're very confident you know what you are doing.

Retrieving lexical hints

$HINT_VALUE = get_hint( $HINT_NAME, \%OPTIONS )

The get_hint() subroutine may be called at compile-time or runtime and expects either one or two arguments:

  • The name of the hint whose value is being retrieved

  • An optional reference to a hash containing named options

The function returns the value of the requested hint, or undef if the hint does not exist.

The only option currently offered is: { up => $UPSCOPE_COUNT }, which works exactly as for set_hint().

In the absence of this option, the hint is retrieved from the scope currently being compiled (at compile-time) or from the lexical scope of current subroutine's immediate caller (at runtime).

However, if the option is included in a runtime call to get_hint(), then the hint is retrieved from the scope indicated. For example:

    set_hint('logging_active' => $FALSE, { up => 1 });

retrieves the 'logging_active' hint from the scope of the current subroutine's caller's caller.

Exporting set_hint() and get_hint() under different names

Normally a use Lexical::Hints exports both set_hints() and get_hints(). However, you can request that these two functions be exported under different names, by specifying the name mappings in the use statement:

    use Lexical::Hints (
        set_hint => 'store_lex_data',
        get_hint => 'retrieve_lex_data',
    );

Debugging lexical hints

Lexical::Hints::dump( \%OPTIONS )

You can always see the current hints of a given lexical scope by placing one of the following statements in that scope:

    # See the hints at compile-time...
    BEGIN { use Data::Dumper 'Dumper'; warn Dumper \%^H; }

    # See the hints at runtime...
    sub { use Data::Dumper 'Dumper'; warn Dumper +(caller 0)[10]; }->();

But those are ugly and hard to remember. So Lexical::Hints provides a utility to encapsulate and enhance them:

    # See the hints at compile-time...
    BEGIN { Lexical::Hints::dump(); }

    # See the hints at runtime...
    Lexical::Hints::dump();

This subroutine is not exported, so calls to it must be fully qualified, as above.

In void context, the subroutine dumps the current contents of the current scope's hints hash to STDERR. In non-void contexts, it returns a string with the serialization of the hints hash:

    # Dump to STDERR...
    Lexical::Hints::dump();

    # Dump to variable...
    my $hints_serialization = Lexical::Hints::dump();

dump() optionally takes a single argument: a reference to a hash of options. At present there is only one option available:

    { up => $UPSCOPE_COUNT }

which is identical in effect to the 'up' options of set_hint() and get_hint(). That is: it selects a higher caller's scope to report on, instead of the immediate caller's.

DIAGNOSTICS

Unknown option: %s

At present, set_hint(), get_hint(), and dump() only accept a single option in their option hashes:

    sethint( $HINT_NAME, $HINT_VALUE, { up => $UPSCOPE_COUNT } )
    gethint( $HINT_NAME,              { up => $UPSCOPE_COUNT } )
    Lexical::Hints::dump(             { up => $UPSCOPE_COUNT } )

You either specified some other option name in your options hash, or else managed to misspell 'up'.

Invalid option: expected hash ref, but was passed %s instead

The optional options argument for set_hint(), get_hint(), and dump() has to be a hash reference. You passed something else.

Useless compile-time 'up' option ignored

The 'up' option only has an effect at run-time; at compile-time it is not meaningful and so is ignored.

Are you sure you understand how the subroutine you called is supposed to work at compile-time? And the runtime-only effect of the 'up' option?

Were you not expecting the call in question to happen at compile-time? Was it unexpectedly called from your import(), or in a BEGIN block?

Or did you just make a cut-and-paste error?

Cannot autovivify hint %s at runtime for %s in call to set_hint()

You attempted to call set_hint() at runtime to set a value for a hint that does not exist.

Because the %^H variable is readonly at runtime, it's only possible to create new hint/value pairs at compile-time. The hint you were trying to set at runtime didn't previously exist in the scope where you were trying to set it, so it could not be created.

Make sure you "predeclare" (at compile-time) any hints that you want to be able to modify at runtime. That is, put a call to set_hint() for those hints inside your import() subroutine.

CONFIGURATION AND ENVIRONMENT

Lexical::Hints requires no configuration files or environment variables.

DEPENDENCIES

None.

INCOMPATIBILITIES

None reported.

BUGS AND LIMITATIONS

This module is not currently thread-safe. Expert advice (or patches!) for thread-safing the module will be most gratefully accepted.

No bugs have been reported.

Please report any bugs or feature requests to bug-lexical-hints@rt.cpan.org, or through the web interface at http://rt.cpan.org.

AUTHOR

Damian Conway <DCONWAY@CPAN.org>

LICENCE AND COPYRIGHT

Copyright (c) 2013, Damian Conway <DCONWAY@CPAN.org>. All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.

DISCLAIMER OF WARRANTY

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.