File: CoreOrPP.pm

package info (click to toggle)
libfunction-fallback-coreorpp-perl 0.090-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 156 kB
  • sloc: perl: 122; makefile: 2
file content (195 lines) | stat: -rw-r--r-- 4,835 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package Function::Fallback::CoreOrPP;

our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
our $DATE = '2020-02-03'; # DATE
our $DIST = 'Function-Fallback-CoreOrPP'; # DIST
our $VERSION = '0.090'; # VERSION

use 5.010001;
use strict;
use warnings;

our $USE_NONCORE_XS_FIRST = 1;

require Exporter;
our @ISA       = qw(Exporter);
our @EXPORT_OK = qw(
                       clone
                       clone_list
                       unbless
                       uniq
               );

sub clone {
    my $data = shift;
    goto FALLBACK unless $USE_NONCORE_XS_FIRST;
    goto FALLBACK unless eval { require Data::Clone; 1 };

  STANDARD:
    return Data::Clone::clone($data);

  FALLBACK:
    require Clone::PP;
    return Clone::PP::clone($data);
}

sub clone_list {
    map { clone($_) } @_;
}

sub _unbless_fallback {
    my $ref = shift;

    my $r = ref($ref);
    # not a reference
    return $ref unless $r;

    # return if not a blessed ref
    my ($r2, $r3) = "$ref" =~ /(.+)=(.+?)\(/
        or return $ref;

    if ($r3 eq 'HASH') {
        return { %$ref };
    } elsif ($r3 eq 'ARRAY') {
        return [ @$ref ];
    } elsif ($r3 eq 'SCALAR') {
        return \( my $copy = ${$ref} );
    } elsif ($r3 eq 'CODE') {
        return sub { goto &$ref };
    } else {
        die "Can't handle $ref";
    }
}

sub unbless {
    my $ref = shift;

    goto FALLBACK unless $USE_NONCORE_XS_FIRST;
    goto FALLBACK unless eval { require Acme::Damn; 1 };

  STANDARD:
    return Acme::Damn::damn($ref);

  FALLBACK:
    return _unbless_fallback($ref);
}

sub uniq {
    goto FALLBACK unless $USE_NONCORE_XS_FIRST;
    goto FALLBACK unless eval { require List::MoreUtils; 1 };

  STANDARD:
    return List::MoreUtils::uniq(@_);

  FALLBACK:
    my %h;
    my @res;
    for (@_) {
        push @res, $_ unless $h{$_}++;
    }
    return @res;
}

1;
# ABSTRACT: Functions that use non-core XS module but provide pure-Perl/core fallback

__END__

=pod

=encoding UTF-8

=head1 NAME

Function::Fallback::CoreOrPP - Functions that use non-core XS module but provide pure-Perl/core fallback

=head1 VERSION

This document describes version 0.090 of Function::Fallback::CoreOrPP (from Perl distribution Function-Fallback-CoreOrPP), released on 2020-02-03.

=head1 SYNOPSIS

 use Function::Fallback::CoreOrPP qw(clone unbless uniq);

 my $clone = clone({blah=>1});
 my $unblessed = unbless($blessed_ref);
 my @uniq  = uniq(1, 3, 2, 1, 4);  # -> (1, 3, 2, 4)

=head1 DESCRIPTION

This module provides functions that use non-core XS modules (for best speed,
reliability, feature, etc) but falls back to those that use core XS or pure-Perl
modules when the non-core XS module is not available.

This module helps when you want to bootstrap your Perl application with a
portable, dependency-free Perl script. In a vanilla Perl installation (having
only core modules), you can use L<App::FatPacker> to include non-core pure-Perl
dependencies to your script.

=for Pod::Coverage ^()$

=head1 FUNCTIONS

=head2 clone($data) => $cloned

Try to use L<Data::Clone>'s C<clone>, but fall back to using L<Clone::PP>'s
C<clone>.

=head2 clone_list(@data) => @data

A shortcut for:

 return map {clone($_)} @data

=head2 unbless($ref) => $unblessed_ref

Try to use L<Acme::Damn>'s C<damn> to unbless a reference but fall back to
shallow copying.

NOTE: C<damn()> B<MODIFIES> the original reference. (XXX in the future an option
to clone the reference first will be provided), while shallow copying will
return a shallow copy.

NOTE: The shallow copy method currently only handles blessed
{scalar,array,hash}ref as those are the most common.

=head2 uniq(@ary) => @uniq_ary

Try to use L<List::MoreUtils>'s C<uniq>, but fall back to using slower,
pure-Perl implementation.

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/Function-Fallback-CoreOrPP>.

=head1 SOURCE

Source repository is at L<https://github.com/perlancar/perl-Function-Fallback-CoreOrPP>.

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Function-Fallback-CoreOrPP>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=head1 SEE ALSO

L<Clone::Any> can also use multiple backends. I used to avoid it because
L<Storable>'s C<dclone> (which is used as the backend) did not support Regexp
objects out of the box until version 3.08. Plus must use deparse to handle
coderefs.

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2020, 2017, 2016, 2014 by perlancar@cpan.org.

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

=cut