in reply to Re^2: Pure perl lexical sub import
in thread Pure perl lexical sub import

Does this meet your requirements?

Test: cat t/01-use.t

package __test__; use v5.22; use warnings; use Test::More; use lib "../lib"; sub dummy {} { my $line = __LINE__; use lexical 'Scalar::Util' => qw/looks_like_number/; is(__LINE__, $line+2, "line numbers are not messed up "); is( defined(&looks_like_number) ,1 ,"sub exists"); is( looks_like_number("42"), 1, "42 is number" ); isnt( looks_like_number("XX"), 1, "XX isn't number" ); is(defined &__test__::dummy, 1, "namespace testable"); isnt( defined(&__test__::looks_like_number) ,1 ,"namespace is clea +n"); } isnt( defined(&looks_like_number) ,1 ,"lex sub doesn't exist out of sc +ope"); diag( "Testing lexical $lexical::VERSION, Perl $], $^X" ); done_testing;

test run

perl /home/lanx/perl/prj/lexical/t/01-use.t ok 1 - line numbers are not messed up ok 2 - sub exists ok 3 - 42 is number ok 4 - XX isn't number ok 5 - namespace testable ok 6 - namespace is clean ok 7 - lex sub doesn't exist out of scope # Testing lexical 0.01, Perl 5.038002, /usr/bin/perl 1..7

Module: cat lib/lexical.pm

package lexical; use v5.22; use strict; use warnings; use Filter::Util::Call ; =head1 NAME lexical - Lexical use of exported functions =head1 VERSION Version 0.01 =cut our $VERSION = '0.01'; =head1 SYNOPSIS Pragma to import subs as lexical_subs into the current scope use lexical "Scalar::Util" => qw/looks_like_number/; print looks_like_number("a15"); =head1 EXPORT No classic exports, the namespace isn't polluted =head1 SUBROUTINES/METHODS =head2 import =cut sub import { my ($my_pkg, $module, @imports) = @_; eval "use $module"; # TODO quick & dirty my $code = q(use experimental 'lexical_subs','refaliasing';); $code .= << "__CODE__" for @imports; # TODO only subs ATM my sub $_; \\&$_ = \\&${module}::$_; __CODE__ upject($code); } sub upject { my $injection = shift; # --- exit if undef return unless defined $injection; # --- adjust line number to disguise injection my ($file,$line) = (caller(2))[1,2]; $line++; $injection .= qq{\n# line $line "$file"\n}; #warn $injection; # --- add source filter filter_add ( sub { my $status = filter_read_exact(1); # read one char into $_ if ( $status > 0) { $_ = $injection .";".$_; # prepend code once filter_del(); # delete source filter } $status ; } ); } =head1 AUTHOR Rolf Michael Langsdorf, C<< <lanx at cpan.org> >> # yadda yadda ... 1; # End of lexical

Cheers Rolf
(addicted to the Perl Programming Language :)
see Wikisyntax for the Monastery

Replies are listed 'Best First'.
Re^4: Pure perl lexical sub import (POC)
by NERDVANA (Priest) on Dec 23, 2024 at 05:14 UTC
    Bingo!
    my sub $_; \\&$_ = \\&${module}::$_;
    This is what I was looking for. And you've packaged it nicely in an importer, too.
      > Bingo!

      Great! =)

      You want it on CPAN?

      I'm still not sure about the right name for the module(s)

      Especially because there are different approaches...

      • Should $variables also be lexically exported? Exporter allows this
      • prior to 5.22 it's only possible to export refs $_ = \&func; like here. Hence lexical::refs ?
      • some wrapped modules (especially pragmas) need to know the calling target module during import, they even bypass exporter.
      Shall I prepare a version injecting the use $module and cleansing the namespace afterwards again? lexical::clean ?

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      see Wikisyntax for the Monastery

        Well, maybe the most appropriate Cpan name would be Importer::Lexical? Since Importer exists...

        The longer story for the situation that triggered the question is that I was working on changes to CodeGen::Cpppp, and one of my goals for that module is to make it fat-packable, or even just drop it's source code in a scripts/ directory alongside the source code of a project written in C. The idea would be to generate the C files if possible, and then write Makefile rules that let people regenerate the files as long as they have perl-5.20 or newer. (without them knowing anything about perl or how to install perl modules). Cpppp currently needs 5.20 and so now I'm debating whether to up that to 5.22.

        Meanwhile, the other reason I wanted to know if there was a way is because I have my own Exporter::Extensible which is currently pure-perl, and can't do lexical exports. Now that I know it's possible without XS, I'd like to add a feature to that so you can say use SomeModuleUsingEE -lexical => 'foo';. This is on my back-burner, but something I'd like to have eventually.

        In the grand scheme of things, I think it's probably better to go with an 'Importer' design than an 'Exporter' design, and if I'd found Importer before I wrote Exporter::Extensible I probably would have gone a different direction, focused on making it easy to AUTOLOAD the generated functions so that Importer can find them.

        In light of all that, I'll let you decide how best to spend your time :-)