Module:...::Scalar(3)

๐Ÿ“ฆ version 1.1.3, in alpine 3.24

๐Ÿ’– Module::Generic::Scalar โ€” String Manipulation Object Class ๐Ÿ’–

okay bestie so this is a User Contributed Perl Documentation page, section 3, and it's literally the glow-up your plain strings have been begging for. no cap. ๐ŸŒธ


โœจ SYNOPSIS โœจ

like, here's the whole vibe at a glance, fr fr:

    my $s = Module::Generic::Scalar->new( "John Doe" );
    print( $s->substr( 0, 4 ), "\n" );
    # prints: John
    $s->append( 'more data' );
    # $a is now a Module::Generic::Array object
    my $a = $s->as_array;
    # $bool is now a Module::Generic::Boolean object
    # with value is true or false depending on underlying value of $s
    my $bool = $s->as_boolean;
    # $a is now a Module::Generic::Number object
    my $n = $s->as_number
    # raw string
    my $str = $s->as_string;
    print( "Hello $s\n" );
    # Hello John Doe

    my $str = Module::Generic::Scalar->new();
    $a->callback( add => sub
    {
        my( $new ) = @_;
        return unless( $$new eq $approved_string );
        return(1);
    });
    $str->append( $some_string );
    # or
    $str .= $some_string;

    $s->capitalise;
    $s->chomp;
    $s->chop;
    $s->clone;
    my $crypted = $s->crypt( $salt );
    $s->defined;
    $s->empty;
    $s->fc( $that );
    my $hex = $s->hex;
    my $index = $s->index;
    $s->is_alpha;
    $s->is_alpha_numeric;
    $s->is_empty;
    $s->is_lower;
    $s->is_numeric;
    $s->is_upper;

    my $s = Module::Generic::Scalar->new( 'Jack John Paul Peter' );
    # Takes the string, split it by space (now an array), join it by comma (now a scalar) and rejoin it with more strings
    say $s->split( qr/[[:blank:]]+/ )->join( ', ' )->join( ', ', qw( Gabriel Raphael Emmanuel ) );
    # prints: Jack, John, Paul, Peter, Gabriel, Raphael, Emmanuel

    $s->lc;
    $s->lcfirst;
    $s->left;
    $s->length;
    my $s = Module::Generic::Scalar->new( "I disapprove of what you say, but I will defend to the death your right to say it" );
    print( "Matches? ", $s->like( qr/\bapprove[[:blank:]\h]+what\b/ ) ? 'yes' : 'no', "\n" ); # print yes
    if( $s->like( qr/[[:blank:]\h]+/ ) )
    {
        # Do something
    }
    # or
    if( my $rv = $s->like( qr/([[:blank:]\h]+)/ )->result )
    {
        my $first_match = $rv->capture->first;
        # Do something
    }

    $s->lower;
    $s->ltrim;
    # Remove all kind of leading whitespaces
    $s->ltrim( qr/[[:blank:]\h]+/ );

    # $s is "Hello world"
    $s->match( 'world' ); # pass
    $s->match( qr/WORLD/i ); # pass
    $s->match( 'monde' ); # obviously fail
    if( $s->match( qr/[[:blank:]\h]+/ ) )
    {
        # Do something
    }
    if( my $rv = $s->match( qr/([[:blank:]\h]+)/ )->result )
    {
        my $first_match = $rv->capture->first;
        # Do something
    }

    my $unpack = $unpack_data->unpack( "A10xA28xA8A*" )->object;
    my $fh = $s->open;
    $fh->print;
    $fh->read;
    $s->ord;
    $s->pack;
    $s->pad( 3, 'X' );
    # XXXHello world

    $s->padd( -3, 'X' );
    # Hello worldXXX
    $s->pos;
    $s->$s->prepend( join( '', qw( Cogito ergo sum ) ) );
    $s->quotemeta;

    # $s is Hello world
    my $rv = $s->replace( ' ', '_' ); # Hello_world
    my $rv = $s->replace( qr/[[:blank:]\h]+/, '_' ); # Hello_world
    if( my $rv = $s->replace( qr/([[:blank:]\h]+)/, '_' )->result )
    {
        my $first_match = $rv->capture->first;
        # Do something
    }
    $s->reset;
    $s->reverse;
    Module::Generic::Scalar->new( "Hello world" )->right( 5 );
    # will produce: world
    $s->rindex;
    # Remove all kind of trailing whitespaces
    $s->rtrim( qr/[[:blank:]\h]+/ );
    $s->scalar;
    $s->set;
    # Returns a Module::Generic::Array object
    my $a = $s->split( /\n/ );
    my $a = $s->split( qr/\n/ );
    $s->sprintf;
    $s->substr;
    $s->tr;
    $s->trim;
    $s->uc;
    $s->ucfirst;
    print( $s->defined ? 'defined' : 'undefined', "\n" );

    my $array = $s->unpack( "W" );
    # Returns the ord() value as a Module::Generic::Array object
    $s->unpack( "W" )->length;
    # Object context. Ditto
    my( $date, $desc, $income, $expend ) = $s->unpack( "A10xA27xA7A*" );
    # Returns a regular list of values
    $s->upper;

๐ŸŽ€ VERSION ๐ŸŽ€

v1.4.3 โ€” that's the one, bestie. ๐Ÿ’…


๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

so the whole point of this class/package is to give you an object-oriented way to mess with strings. it's giving "strings but make it a whole person." โœจ

the object is overloaded, which means when you use it as a string, it just hands back the embedded string. iconic behaviour honestly:

    print( "I met with $s\n" );

and that would produce: I met with John Doe


๐ŸŒˆ METHODS ๐ŸŒˆ

๐Ÿ’œ new

you hand it a scalar reference, an array, or just a regular plain string, and it gives you back a shiny new object. ๐Ÿซถ

if you pass it an array reference or an array-based object like Module::Generic::Array, it will concatenate all the array elements together. slay.


๐Ÿ’œ append

give it a string and it adds that string to the end of your string object. no drama.

    # $s is 'Hello'
    $s->append( ' world' );
    # now this is: Hello world

๐Ÿ’œ as_array

returns the current string value as an Module::Generic::Array object. ๐Ÿงš


๐Ÿ’œ as_boolean

returns a Module::Generic::Boolean object, with its value set to true or false depending on the value of the scalar object. vibe check time:

    # $s is 1
    $s->as_boolean; # sets to true
    # $s is 0
    $s->as_boolean; # sets to false
    # $s is hello
    $s->as_boolean: # sets to true
    # $s is undefined or empty
    $s->as_boolean: # sets to false
    # etc...

Module::Generic::Boolean objects are genuinely so useful, bestie โ€” in perl they act like 0 or 1 to show false or true, but when you use them in json, they get automatically converted into "false" or "true". like, multilingual queen. ๐Ÿ‘‘


๐Ÿ’œ as_number

returns the current string as an Module::Generic::Number object. ๐Ÿ”ข


๐Ÿ’œ as_string

returns the object string as a, you guessed it, string. ๐Ÿ’–

    my $s = Module::Generic::Scalar->new( "Mary Jane" );
    print( "Hello $s\n" );
    # Hello Mary Jane

๐Ÿ’œ callback

sets or gets a callback on the scalar object. you can set 2 types of callback: "add" or "remove", and they get called respectively when you add something to the scalar, or when you remove something from it. ๐ŸŽ€

how does it even do that? it ties the scalar to its internal class Module::Generic::Scalar::Tie, which will call the "add" or "remove" callback whenever data is being added or removed โ€” no matter how, i.e. whether it's through the methods of this class, or by you just directly trying to add data to it:

    my $str = Module::Generic::Scalar->new();
    $a->callback( add => sub
    {
        my( $new ) = @_;
        return unless( $$new eq $approved_string );
        return(1);
    });
    $str->append( $some_string );
    # or
    $str .= $some_string;

in both cases above the string will be added โ€” and if it were some other unapproved text, the data would not get added to the string. gatekeeping, but make it responsible. ๐Ÿ™ˆ

so the callback must return true to allow the data to be added, or undef to refuse. and heads up: returning an empty string or 0 will not work as a rejection, even though those are false values. yes, really. ๐Ÿ’€

both the "add" and "remove" callbacks receive an hash reference as their sole argument.

the "add" callback receives an hash reference with these properties:

  • added โ€” a scalar reference to the new value being set in replacement of the old one, so you can inspect it. ๐Ÿ”
  • removed โ€” a scalar reference to the old value being replaced, so you can inspect it.
  • type โ€” the callback type: "add"

the "remove" callback works exactly the same way, but for any operation that tries to remove data from the string. it receives an hash reference with these properties:

  • removed
  • type โ€” the callback type: "remove"
    my $str = Module::Generic::Scalar->new();
    $str->callback( remove => sub
    {
        my( $old, $new ) = @_;
        # Do some check to accept or reject
        return(1); # always return true to accept
    });
    $str->substr( 3, 4, $some_other_text ); # Attempt to change the string

this example above would call the callback passing it the old and new string. ๐Ÿซถ

to replace a callback, just add another one โ€” it'll replace the previous one. easy.

you can get the callback code associated with a callback by calling "callback" with one argument: the callback type.

    my $code_ref = $str->callback( 'add' );

to remove a callback, pass undef:

    $str->callback( add => undef );
    $str->callback( remove => undef );

by default, a scalar object is not tied to Module::Generic::Scalar::Tie and no callbacks are set nor used. be mindful when using callbacks, since it will slow things down a little bit โ€” even though it's a very thin layer. ๐Ÿ˜ญ

see perltie for more info on tieing data.


๐Ÿงต THREAD SAFETY ๐Ÿงต

the "callback" method installs internal hooks that are triggered on scalar value mutation (e.g., when a new value is assigned). these callbacks are enabled by tying the scalar to an internal package (not part of the public API). ๐Ÿ”ฅ

while this design is fully safe in single-threaded use, note the following if you're working in a multi-threaded environment:

  • Callbacks may be triggered by assignments to the scalar value โ€” e.g., $$scalar = "new value".
  • If the scalar object is accessed by multiple threads, and a callback mutates shared state, this may lead to race conditions unless external locking is applied. โš ๏ธ
  • It is recommended that each scalar object be thread-local, or that the callback logic be thread-safe.

the internal tied object is not exposed, and should not be accessed directly. don't do it bestie, i'm serious. ๐Ÿ’€


๐Ÿ’œ capitalise

returns a new Module::Generic::Scalar object representing the string with the words capitalised โ€” done in a smart way. meaning the special words like "and", "but", "if", "on", "or", "the", "to", etc. are not capitalised. taste! ๐Ÿ‘‘

this is based on the work done by John Gruber and Aristotle Pagaltzis https://gist.github.com/gruber/9f9e8650d68b13ce4d78


๐Ÿ’œ chomp

just like "chomp" in perlfunc, this removes the trailing new lines in the string object, if any. ๐Ÿ“

and per the perl documentation for "chomp" in perlfunc: "it returns the total number of characters removed from all its arguments."


๐Ÿ’œ chop

just like "chop" in perlfunc, this removes the trailing character in the string object, no matter what it is, and returns the character chopped. savage but fair. โœ‚๏ธ


๐Ÿ’œ clone

returns a copy of the object. ๐Ÿฆ‹


๐Ÿ’œ crypt

this takes a "salt" and returns an encrypted version of the string. see "crypt" in perlfunc. โš ๏ธ note that this does not work well on some BSD systems.


defined ๐Ÿ’–

Okay so this one is a vibe check: it returns true or false whether the string object contains a defined string, i.e. not undef.


empty ๐Ÿซถ

Alias for reset. This empties the scalar object, making it zero-byte in length. Iconic little reset button energy.


error ๐Ÿ˜ญ

Provided with an error message string, or a hash of parameters, and this will instantiate a new exception object and return undef, or return a Module::Generic::Null object in object context, such as when it is chained.

See error in Module::Generic for more information. No cap, thatโ€™s the whole tea.


fc ๐Ÿฆ‹

Just like fc in perlfunc, provided with a string, this enables comparison with casefolding.

To quote from the manual: โ€œCasefolding is the process of mapping strings to a form where case differences are erasedโ€.

lc($this) eq lc($that)    # Wrong!
# or
uc($this) eq uc($that)    # Also wrong!
# or
$this =~ /^\Q$that\E\z/i  # Right!
# And now
my $s = Module::Generic::Scalar( $this );
$s->fc( $that );

hex โœจ

Returns the hex value of the string. Cute, concise, does exactly what it says.


index ๐Ÿ”

Given a sub string and an optional position, and this returns the position at which the sub string was found, as a Module::Generic::Number object.

See index in perlfunc.


is_alpha ๐Ÿ’…

Returns true if the string contains only alphabetic characters, or else it returns false.

This uses perlโ€™s [[:alpha:]] to test.


is_alpha_numeric ๐ŸŽ€

Returns true if the string contains only alphabetic or numeric characters, or else it returns false.

This uses perlโ€™s [[:alnum:]] to test.


is_empty ๐Ÿซง

Returns true if the string is zero in length, or else it returns false.


is_lower ๐ŸŒธ

Returns true if the string contains only lower case characters, or else it returns false.

This uses perlโ€™s [[:lower:]] to test.


is_numeric ๐Ÿ”ข

Returns true if the string contains only numeric characters, or else it returns false.

This uses looks_like_number in Scalar::Util.


is_upper ๐Ÿ‘‘

Returns true if the string contains only upper case characters, or else it returns false.

This uses perlโ€™s [[:upper:]] to test.


join ๐Ÿงš

Takes a string as the delimiter and one or more elements and this will join the current string object and the other string elements provided using the string delimiter. For example:

my $s = Module::Generic::Scalar->new( 'Jack John Paul Peter' );
# Takes the string, split it by space (now an array), join it by comma (now a scalar) and rejoin it with more strings
say $s->split( qr/[[:blank:]]+/ )->join( ', ' )->join( ', ', qw( Gabriel Raphael Emmanuel ) );
# prints: Jack, John, Paul, Peter, Gabriel, Raphael, Emmanuel

Note that if, among the element passed to join, an array object is provided, it will not be expanded. Thus, if you do something like this:

my $a = Module::Generic::Array->new( [qw( John Peter )] );
say Module::Generic::Scalar->new( 'Paul' )->join( ', ', $a );

It will not produce Paul, John, Peter, but instead something like: Paul, Module::Generic::Array=ARRAY(0x5646f0116470).

Thatโ€™s because there is no way to guess if the user wanted to pass on a list or just an object and making that kind of assumption is dangerous.

What you would want to do instead is:

say Module::Generic::Scalar->new( 'Paul' )->join( ', ', $a->list );

Or maybe

say Module::Generic::Scalar->new( 'Paul' )->join( ', ', @$a );

Of course, passing an overloaded object that has the stringification capability will transform it automatically into a string before being joined. Thus:

my $word1 = Module::Generic::Scalar->new( 'Hello' );
my $word2 = Module::Generic::Scalar->new( 'world' );
say $word1->join( ' ', $word2 );

will yield: Hello world because Module::Generic::Scalar objects have overloaded stringification capability.

It returns the newly formed string as a new Module::Generic::Scalar object. Slay.


lc ๐ŸŒˆ

Takes the current string object and returns a new Module::Generic::Scalar object with the string all in lower case.


lcfirst ๐Ÿ“

Takes the current string object and returns a new Module::Generic::Scalar object with the first character of the string in lower case.


left โฌ…๏ธ

Provided with a number and this will get the chunk starting from the left of the string object.

Module::Generic::Scalar->new( "Hello world" )->left( 5 );
# will produce: Hello

See also right.


length ๐Ÿ“

This returns the length of the string, as a Module::Generic::Number object.


like ๐Ÿ’œ

Provided with a string or a regular expression and this returns the value of the regular expression evaluation against the object string.

my $s = "I disapprove of what you say, but I will defend to the death your right to say it";
print( "Matches? ", $s->like( qr/\bapprove[[:blank:]\h]+what\b/ ) ? 'yes' : 'no', "\n" ); # print yes

If there is no match, it returns 0, but in object, list or scalar context or when there are matches, it returns a Module::Generic::RegexpCapture object. This object stringifies into the number of matches, so you can do:

if( $s->like( qr/[[:blank:]\h]+/ ) )
{
    # Do something
}

or

if( my $rv = $s->like( qr/([[:blank:]\h]+)/ )->result )
{
    my $first_match = $rv->capture->first;
    # Do something
}

Regular expression can also be one from Regexp::Common.

See also match and replace.


lower ๐ŸŒธ

Alias for lc. Same lowercase fantasy, different label.


ltrim ๐Ÿงผ

This removes any new line and space characters, i.e. "\r" and "\n" at the beginning of the string.

It takes an optional argument that can be an alternative string to remove at the end of the sstring or a regular expression, such as one provided with perlfunc/qr.

$s->ltrim( qr/[[:blank:]\h]+/ ); # Remove all kind of leading whitespaces

It returns the object itself for chaining.

Regular expression can also be one from Regexp::Common.

See also rtrim.


match ๐Ÿ”ฅ

Provided with a string or a regular expression like the one created with qr in perlfunc and this returns true or false whether the string object matched or not.

# $s is "Hello world"
$s->match( 'world' ); # pass
$s->match( qr/WORLD/i ); # pass
$s->match( 'monde' ); # obviously fail

If there is no match, it returns 0, but in object, list or scalar context or when there are matches, it returns a Module::Generic::RegexpCapture object. This object stringifies into the number of matches, so you can do:

if( $s->match( qr/[[:blank:]\h]+/ ) )
{
    # Do something
}

or

if( my $rv = $s->match( qr/([[:blank:]\h]+)/ )->result )
{
    my $first_match = $rv->capture->first;
    # Do something
}

Regular expression can also be one from Regexp::Common.

See also like and replace.


object ๐Ÿชž

Returns the current object. This is useful when chaining to force an object context. For example, with unpack. In scalar context, unpack, as per the unpack in perlfunc documentation will return the first element:

my $unpack = $unpack_data->unpack( "A10xA28xA8A*" );

But what if we wanted $unpack to not be the first element, but the array object? For that, we would need to call unpack in object context:

my $unpack = $unpack_data->unpack( "A10xA28xA8A*" )->object;

Main character energy: force the object context.


open ๐Ÿšช

Opens the scalar in read/write mode and returns an object with same capabilities as regular file handle.


ord ๐Ÿ”ก

This returns the value of ord in perlfunc on the string, as a Module::Generic::Number object.


pack ๐ŸŽ

Like pack in perlfunc, this takes a template and convert the string object. โ€œThe resulting string is the concatenation of the converted values.โ€

It returns a new Module::Generic::Scalar object.

See also pack in Module::Generic::Array.


pad ๐Ÿงธ

Provided with a number n and a string and this will create n instance of the string. If the number is positive, the string will be placed at the beginning and if negative, it will be placed at the end.

$s->pad( 3, 'X' );
# XXXHello world

$s->padd( -3, 'X' );
# Hello worldXXX

pass_error ๐Ÿ’€

If provided with an error object, this will set it in this package and pass it along to the caller.

If no error object is provided, this will merely return undef, or an Module::Generic::Null object in object context, such as when it is chained.

See pass_error in Module::Generic for more information.


pos ๐Ÿ“

This sets or gets the position inside the string object. See pos in perlfunc for detail about this.


prepend ๐Ÿซถ

Takes some data as its unique argument and prepend it to the scalar object underlying value.

If you want to pass multiple data, you will have to join them first:

$s->prepend( join( '', qw( Cogito ergo sum ) ) );

quotemeta ๐Ÿ›ก๏ธ

Given a string, this returns a new Module::Generic::Scalar object with the given string characters escaped with quotemeta in perlfunc.


replace ๐Ÿ”

Provided with a string or a regular expression and a replacement string and this will replace all instance of the string or regular expression with the replacement string provided.

# $s is Hello world
my $rv = $s->replace( ' ', '_' ); # Hello_world
my $rv = $s->replace( qr/[[:blank:]\h]+/, '_' ); # Hello_world

If there is no match, it returns 0, but in object, list or scalar context or when there are matches, it returns a Module::Generic::RegexpCapture object. This object stringifies into the number of matches, so you can do:

if( $s->replace( qr/[[:blank:]\h]+/, '_' ) )
{
    # Do something
}

or

if( my $rv = $s->replace( qr/([[:blank:]\h]+)/, '_' )->result )
{
    my $first_match = $rv->capture->first;
    # Do something
}

Regular expression can also be one from Regexp::Common.

See also like and match.


reset โ™ป๏ธ

This empty the string inside the object.


reverse ๐Ÿ”„

Given a string, this returns a new Module::Generic::Scalar object with the given string in reverse order.


Provided with a number and this will get the chunk starting from the right of the string object.

Module::Generic::Scalar->new( "Hello world" )->right( 5 );
# will produce: world

See also left.


rindex ๐Ÿ”Ž

Given a sub string and an optional position, and this returns the position at which the sub string was found, starting from the end.

See rindex in perlfunc.


rtrim ๐ŸŒธ

This removes any new line and space characters, i.e. "\r" and "\n" at the end of the string.

It takes an optional argument that can be an alternative string to remove at the end of the sstring or a regular expression, such as one provided with perlfunc/qr.

$s->rtrim( qr/[[:blank:]\h]+/ ); # Remove all kind of trailing whitespaces

It returns the object itself for chaining. Chain goes on, periodt.

Regular expression can also be one from Regexp::Common ๐Ÿ’–

See also ltrim ๐Ÿซถ

scalar ๐Ÿงฎ

Returns the string chillinโ€™ inside this scalar object. It calls as_string.

set ๐ŸŽ€

Hand it a scalar reference or a scalar-based object like Module::Generic::Scalar, or an array reference, and it sets the current string.

It acts the exact same way as for new, except it acts on the current object string. Periodt.

split โœ‚๏ธ

Give it a string or an expression, and it returns the list in list context or, in scalar context, an array reference as a Module::Generic::Array object.

Be careful that you cannot just do like perlโ€™s original split such as:

my $a = $s->split( /\n/ );

Because /\n/ is not passed as an argument, i.e. it results in no argument being passed, so you do need to either provide the expression as "\n" or as a regular expression:

my $a = $s->split( qr/\n/ );

It will warn you if no argument was provided.

Regular expression can also be one from Regexp::Common.

sprintf ๐Ÿง

Provided with a list of arguments, and this replaces the placeholders just like sprintf in perlfunc does.

substr ๐Ÿช„

Provided with an offset, an optional length and an optional replacement string, and this modifies in-place the current object string and returns a new Module::Generic::Scalar object of the string segment thus altered or removed or replaced.

See substr in perlfunc for more information.

$s = 'I disapprove of what you say, but I will defend to the death your right to say it'; # Evelyn Hall, "Friends of Voltaire"
$s->substr( 2, 13 );
# returns a new object containing 'disapprove of'
$s->substr( 2, 13, 'really do not approve' );
# returns a new object containing 'disapprove of' and the current object now contains:
# 'I really do not approve what you say, but I will defend to the death your right to say it'

tr ๐Ÿ”

Provided with a search list and a replacement list and this will perform just like the perl core tr in perlfunc function.

It also accepts options like cdsr and returns the resulting value.

THREAD SAFETY AND SECURITY WARNING โš ๏ธ

The tr method uses eval to dynamically apply a transliteration pattern:

$$self =~ tr/$search/$replace/$opts/;

This can be considered safe as long as the $search and $replace values come from a trusted source. However, if untrusted user input is passed to these arguments, it could result in a malformed or dangerous regular expression being compiled at runtime.

To ensure safety:

  • Only use static or validated content in $search and $replace
  • Avoid using this method inside threads with shared objects unless the object is guarded externally

trim ๐Ÿงผ

Provided with a target string or a regular expression, and this will remove any occurrence of them in the string object.

uc ๐Ÿ” 

Takes the current string object and returns a new Module::Generic::Scalar object with the string all in upper case.

ucfirst ๐ŸŒŸ

Takes the current string object and returns a new Module::Generic::Scalar object with the first character of the string in upper case.

undef ๐Ÿซฅ

Sets the underlying string object to undef.

This would make

print( $s->defined ? 'defined' : 'undefined', "\n" );

return false, but be careful that you cannot do:

print( $s ? 'defined' : 'undefined', "\n" );

Because $s is the object so it would always return true.

If you stringify it like

print( "$s" ? 'defined' : 'undefined', "\n" );

It would still return as defined, because this would be a defined string, albeit empty.

unpack ๐Ÿ“ฆ

my $array = $s->unpack( "W" );
# Returns the ord() value as a Module::Generic::Array object
$s->unpack( "W" )->length;
# Object context. Ditto
my( $date, $desc, $income, $expend ) = $s->unpack( "A10xA27xA7A*" );
# Returns a regular list of values

Does the reverse of pack. Provided with a template, it takes the string object and expands it out into a list of values.

It returns an Module::Generic::Array object in object or scalar context, and a regular list in list context.

upper โฌ†๏ธ

Alias for uc.

SERIALISATION ๐Ÿงš

Serialisation by CBOR, Sereal and Storable::Improved (or the legacy Storable) is supported by this package. To that effect, the following subroutines are implemented: FREEZE, THAW, STORABLE_freeze and STORABLE_thaw.

THREAD-SAFETY ๐Ÿงต

This module is designed to be fully thread-safe and process-safe, ensuring data integrity across Perl ithreads and mod_perlโ€™s threaded Multi-Processing Modules (MPMs) such as Worker or Event. It relies on Module::Generic::Global for thread-safe storage of shared state and employs synchronisation mechanisms to prevent data corruption and race conditions.

Synchronisation Mechanisms ๐Ÿ”’

  • Shared State

The module uses Module::Generic::Global to manage shared state in two namespaces:

  • "errors": Stores error objects for "error" and "pass_error", keyed by object reference address, process ID, and thread ID (if applicable).
  • "loaded_classes": Tracks loaded classes in "_load_class", keyed by class name and thread ID (if applicable).

These repositories are ":shared" when "CAN_THREADS" is true (Perl supports ithreads), protected by "lock" in perlfunc for Perl threads or APR::ThreadRWLock for mod_perl threaded MPMs without threads. In non-threaded environments, repositories are per-process, requiring no synchronisation.

  • Tied Scalars

When callbacks are set via "callback", the scalar is tied to "Module::Generic::Scalar::Tie". As of version 1.4.3, tied scalar operations (e.g., "STORE", "FETCH") are thread-safe, as they rely on Module::Generic::Globalโ€™s synchronisation. However, callbacks themselves are not inherently thread-safe. If a callback accesses shared resources or performs complex operations, you must implement additional synchronisation (e.g., using "lock" in perlfunc or Thread::Semaphore).

Context Key Isolation ๐Ÿ”‘

Module::Generic::Global uses context keys to isolate data:

  • Object-Level Keys

Methods like "error", "pass_error", and "DESTROY" use object-level keys ("<refaddr>;<pid>[;<tid>]"), where "refaddr" is the objectโ€™s reference address, "pid" is the process ID, and "tid" is the thread ID (if "HAS_THREADS" is true). This ensures thread- and process-specific isolation for errors.

  • Class-Level Keys

"_load_class" uses class-level keys ("<class>[;<tid>]"), isolating loaded class tracking per thread or process.

Keys differ between threaded ("<refaddr>;<pid>;<tid>") and non-threaded ("<refaddr>;<pid>") environments, preventing cross-context interference.

Error Handling ๐Ÿ˜ญ

Errors are stored in the "errors" namespace, with one error per object-process-thread combination. The package-global $ERROR is retained for backward compatibility but is not cleared in "DESTROY" to avoid affecting other objects. Errors are serialised using Storable::Improved for thread compatibility.

mod_perl Considerations ๐Ÿช

  • Prefork MPM

Data is per-process, requiring no additional synchronisation.

  • Threaded MPMs (Worker/Event)

Shared repositories are protected by Module::Generic::Globalโ€™s synchronisation. Users should call "Module::Generic::Global-"cleanup_register> in mod_perl handlers to clear repositories after requests, preventing memory leaks.

  • Thread-Unsafe Functions

Avoid Perl functions like "localtime", "readdir", "srand", or operations like "chdir", "umask", "chroot" in threaded MPMs, as they may affect all threads. Consult perlthrtut at http://perldoc.perl.org/perlthrtut.html and mod_perl documentation at https://perl.apache.org/docs/2.0/user/coding/coding.html#Thread_environment_Issues for details.

Recommendations for Threaded Applications ๐Ÿ’ก

  • Use non-tied scalars without additional synchronisation, as Module::Generic::Global handles shared state.
  • For tied scalars, ensure callbacks are thread-safe by adding locks for shared resources.
  • In mod_perl, use "cleanup_register" to manage memory.

SEE ALSO ๐Ÿ‘€

Module::Generic::Number, Module::Generic::Array, Module::Generic::Boolean, Module::Generic::Hash, Module::Generic::Dynamic

AUTHOR โœ๏ธ

Jacques Deguest jack@deguest.jp

Copyright (c) 2000-2024 DEGUEST Pte. Ltd.

You can use, copy, modify and redistribute this package and associated files under the same terms as Perl itself.


Thatโ€™s the whole page, bestie โ€” rendered by perl v5.42.2 on 2026-02-15 for Module:...::Scalar(3). ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from