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

Dear monks,

Probably a novice question: I often find myself putting the same few lines at the top of my programs – something like

use strict; use warnings; use feature 'say'; use utf8; binmode(STDOUT, ":utf8"); use Encode qw(decode_utf8 encode_utf8); use open qw(:encoding(UTF-8) :std); use List::Util 'shuffle'; use mygenericmodule;

Is there a way to include those other things in my own module, so I can just use mygenericmodule and get the rest of them along with it?

Replies are listed 'Best First'.
Re: Passing on "use"s
by kcott (Archbishop) on Oct 29, 2023 at 15:25 UTC

    G'day Chuma,

    A "use VERSION" may get you a fair selection of what you want (plus others depending on the value of VERSION). A "use v5.36" automatically gives you the first three in your list (plus others).

    You may find Modern::Perl useful. See its source to get an idea of how to implement a custom version for your specific needs.

    — Ken

      Thanks! That source code looks like it might have the answer somewhere... but it's a little too advanced for me to figure out. Suppose I just wanted "say" – I tried

      use feature(); sub import{feature->import('say')}

      but that doesn't seem to do anything.

      EDIT: It needed a package name, I guess. Seems to work now!

Re: Passing on "use"s
by 1nickt (Canon) on Oct 29, 2023 at 16:05 UTC

    Is there a way to include those other things in my own module, so I can just use mygenericmodule and get the rest of them along with it?

    Yep: see Import::Into.

    Hope this helps!


    The way forward always starts with a minimal test.

      Looks nice! So, uh...

      use Import::Into; sub import{ feature->import::into(scalar caller,'say'); }

      That doesn't seem to do anything either. What am I missing?

        GenericModule.pm:

        package GenericModule; use Import::Into; feature->import::into(1, 'say'); 1;

        111155275.pl:

        use GenericModule; say 'hello,world';

        Script run:

        $ perl -I. 111155275.pl hello,world

        Hope this helps!


        The way forward always starts with a minimal test.
Re: Passing on "use"s
by eyepopslikeamosquito (Archbishop) on Oct 29, 2023 at 22:32 UTC
Re: Passing on "use"s
by cavac (Prior) on Nov 02, 2023 at 13:52 UTC

    For many of my projects, i use a script to update the standard pragmas in all files. A typical module might begin with:

    package PageCamel::Web::ListAndEdit::Main; #---AUTOPRAGMASTART--- use v5.36; use strict; use diagnostics; use mro 'c3'; use English; use Carp qw[carp croak confess cluck longmess shortmess]; our $VERSION = 4.2; use autodie qw( close ); use Array::Contains; use utf8; use Data::Dumper; use Data::Printer; use builtin qw[true false is_bool]; no warnings qw(experimental::builtin); use PageCamel::Helpers::UTF; #---AUTOPRAGMAEND--- use base qw(PageCamel::Web::BaseModule); ...

    Since things change over the years, i've written a script and that's the ONLY place in a project that needs manual adapting. Technically, i can even open a new, empty file and just paste in the AUTOPRAGMA lines and run the script. But for new files, ye olde copy&paste is usually faster.

    Here's my script:

    #!/usr/bin/env perl #---AUTOPRAGMASTART--- use v5.36; use strict; use diagnostics; use mro 'c3'; use English; use Carp qw[carp croak confess cluck longmess shortmess]; our $VERSION = 4.2; use autodie qw( close ); use Array::Contains; use utf8; use Data::Dumper; use Data::Printer; use builtin qw[true false is_bool]; no warnings qw(experimental::builtin); use PageCamel::Helpers::UTF; #---AUTOPRAGMAEND--- # PAGECAMEL (C) 2008-2020 Rene Schickbauer # Developed under Artistic license print "Searching files...\n"; my @files = (find_pm('lib'), find_pm('devscripts')); #my @files = find_pm('server'); print "Changing files:\n"; foreach my $file (@files) { my $inserted = 0; print "Editing $file...\n"; my @lines; open(my $ifh, "<", $file) or die($ERRNO); @lines = <$ifh>; close $ifh; open(my $ofh, ">", $file) or die($ERRNO); foreach my $line (@lines) { if($line =~ /^use\ +(.+)\;/) { my $pragma = $1; my $skip = 0; if($pragma =~ /(strict|warnings|English|mro|diagnostics|Ca +rp|Fatal|Array\:\:Contains|autodie|utf8|Encode|Data\:\:Dumper|Helpers +\:\:UTF|builtin|Data\:\:Printer)/ && $pragma !~ /Digest/) { # Remove this (old) lines $skip = 1; } if($pragma =~ /(5.\d+)/ && $pragma !~ /Digest/) { # Always update the required perl version $skip = 1; } if($file =~ /Helpers\/UTF\.pm$/ && $pragma =~ /Encode/) { # Don't skip this one instance, this is the only place + that loads the Encode module $skip = 0; } if($skip) { next; } } if($line =~ /^no\ if.*experimental\:\:smartmatch/) { next; } if($line =~ /^(our|my) \$VERSION/) { next; } # Handle sub "signatures" if($line =~ /^use\ feature\ \'signatures\'/ || $line =~ /^no\ +warnings\ .*experimental\:\:signatures/) { next; } # Handle the new "builtin" stuff if($line =~ /^no\ warnings\ .*experimental\:\:builtin/) { next; } if($line =~ /^\#\-\-\-AUTOPRAGMA/) { next; } print $ofh $line; if($inserted) { # Already inserted the pragmas next; } if($line =~ /^package\ / || $line =~ /^\#\!/) { print $ofh "#---AUTOPRAGMASTART---\n"; print $ofh "use v5.36;\n"; print $ofh "use strict;\n"; print $ofh "use diagnostics;\n"; print $ofh "use mro 'c3';\n"; print $ofh "use English;\n"; print $ofh "use Carp qw[carp croak confess cluck longmess +shortmess];\n"; print $ofh "our \$VERSION = 4.2;\n"; print $ofh "use autodie qw( close );\n"; print $ofh "use Array::Contains;\n"; print $ofh "use utf8;\n"; print $ofh "use Data::Dumper;\n"; print $ofh "use Data::Printer;\n"; print $ofh "use builtin qw[true false is_bool];\n"; print $ofh "no warnings qw(experimental::builtin);\n"; if($file !~ /Helpers\/UTF\.pm$/) { print $ofh "use PageCamel::Helpers::UTF;\n"; } print $ofh "#---AUTOPRAGMAEND---\n"; $inserted = 1; } } close $ofh; } print "Done.\n"; exit(0); sub find_pm($workDir) { my @files; opendir(my $dfh, $workDir) or die($ERRNO); while((my $fname = readdir($dfh))) { next if($fname eq "." || $fname eq ".." || $fname eq ".hg"); $fname = $workDir . "/" . $fname; if(-d $fname) { push @files, find_pm($fname); } elsif($fname =~ /\.p[lm]$/i && -f $fname) { push @files, $fname; } } closedir($dfh); return @files; }

    PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP
      What irritates me is the duplicity duplication. Wouldn't it be nicer to copy the autopragma part from the script itself instead of repeating it in prints? ;-)

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

        Hmm, the script also edits itself during update, using the logic defined in the function. But your solution would work, too.

        PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP
      Why the explicit 'use strict' when you're already loading 'v5.36' ?
        Why the explicit 'use strict' when you're already loading 'v5.36' ?

        Having both allows to later change your mind and support older Perl versions (perhaps because someone paid for that). Removing use v5.36 would implicitly disable strict otherwise.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

        Yes, it's technically not required. But after nearly two decades of me preaching to other people to "use strict", a Perl script without that line just freaks me out. The force of habit is strong in this one...

        PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP