Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

This seems crazy but it actually works! Tests show this only happens if the module doesn't use other modules or compile. If dependencies can be handled then Perl could use even more CPAN modules that are not installed! Thoughts?
#!/usr/bin/perl -l # Use a CPAN module that is *not* installed! Is this a good idea? # Posted to perlmonks.org by an Anonymous Monk on Sun Jun 17 2018 # # In this example, if the Astro::MoonPhase module is not installed, # the use_cpan sub will parse the error, download the module page # from metacpan, parse that for the source code uri, download the # raw module source, eval that string, and proceed normally as if # the module was installed! It does not work with all modules and # the concept is presented to the Monastery for contemplation. #__QKB__ use strict; use warnings; eval { require Astro::MoonPhase }; use_cpan($@) if $@; my @phases = Astro::MoonPhase::phasehunt(); print q~LOCALTIME = ~, scalar localtime time; print q~New Moon = ~, scalar localtime $phases[0]; print q~First quarter = ~, scalar localtime $phases[1]; print q~Full moon = ~, scalar localtime $phases[2]; print q~Last quarter = ~, scalar localtime $phases[3]; print q~New Moon = ~, scalar localtime $phases[4]; sub use_cpan { my ($module) = @_; if ($module =~ /install the (\S+) module/) { my $modname = $1; require HTTP::Tiny; my $pm = HTTP::Tiny->new->get("https://metacpan.org/pod/$m +odname"); for ($pm->{content} =~ /Source<\/a>\s*\(<a href="([^"]+)"> +raw/) { $pm = HTTP::Tiny->new->get($1); eval $pm->{content}; last } } }

Hack away...

Replies are listed 'Best First'.
Re: Use a CPAN module that is not installed! Is this a good idea?
by syphilis (Archbishop) on Jun 18, 2018 at 04:55 UTC
    Thoughts?

    Take a look at Acme::Everything, which takes the idea a little further. AIUI, one can do stuff like:
    > perl -MAcme::Everything -le 'print Math::GMP->new(42);'
    and if Math::GMP has been installed, then it will be loaded and the code executed.
    If Math::GMP has not been installed, then it (and any missing dependencies) will be installed, loaded, and the code then executed.

    However, I've not tried Acme::Everything - nor am I likely to ;-)
    I think it was done merely as a quirky bit of fun.

    Cheers,
    Rob
Re: Use a CPAN module that is not installed! Is this a good idea?
by usemodperl (Beadle) on Jun 18, 2018 at 19:21 UTC
    CPAN as a cloud API. Good idea if you can't install modules. This version caches a copy of the downloaded module to a folder named .perlmod in the working directory.:
    #!/usr/bin/perl -l # Use a CPAN module that is *not* installed! Is this a good idea? # Posted to perlmonks.org by an Anonymous Monk on Sun Jun 17 2018 # # In this example, if the Astro::MoonPhase module is not installed, # the use_cpan sub will parse the error, download the module page # from metacpan, parse that for the source code uri, download the # raw module source, eval that string, and proceed normally as if # the module was installed! It does not work with all modules and # the concept is presented to the Monastery for contemplation. #__QKB__ # Hacked by usemodperl: use Carp. Added module cache. use strict; use warnings; use Carp 'croak'; eval { require Astro::MoonPhase }; use_CPAN($@) if $@; my @phases = Astro::MoonPhase::phasehunt(); print q~LOCALTIME = ~, scalar localtime time; print q~New Moon = ~, scalar localtime $phases[0]; print q~First quarter = ~, scalar localtime $phases[1]; print q~Full moon = ~, scalar localtime $phases[2]; print q~Last quarter = ~, scalar localtime $phases[3]; print q~New Moon = ~, scalar localtime $phases[4]; sub use_CPAN { local ($_) = @_; if (/install the (\S+) module/) { my $module = $1; my $moddir = '.perlmod'; (my $modloc = $module) =~ s/::/__/g; $modloc = "$moddir/$modloc"; if (-d $moddir and -e $modloc) { open my $fh, '<', $modloc or croak "$!"; @_ = <$fh>; close $fh; $_ = join "\n", @_; eval $_ or croak; } else { require HTTP::Tiny; $_ = HTTP::Tiny->new->get("https://metacpan.org/pod/$modul +e"); croak unless $_->{content}; for ($_->{content} =~ /Source<\/a>\s*\(<a href="([^"]+)">r +aw/) { $_ = HTTP::Tiny->new->get($1); $_ = $_->{content} ? $_->{content} : croak; eval $_ or croak; eval mkdir $moddir; croak $@ if $@; if (open my $fh, '>', $modloc or croak "$!") { print $fh $_; close $fh; } last } } } }
    The programmer is fighting against the two most destructive forces in the universe: entropy and human stupidity.—Damian Conway