Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Re^3: Importing multiple %EXPORT_TAGS

by jcb (Parson)
on Dec 28, 2020 at 01:57 UTC ( [id://11125849]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Importing multiple %EXPORT_TAGS
in thread Importing multiple %EXPORT_TAGS

If I read that correctly, you might want to check your namespace after importing :all...

The _add_private sub will be called while initializing %EXPORT_TAGS, and it modifies @EXPORT_OK, which is also used to define (by reference) the :all tag. Data::Dumper should illustrate this if asked to dump the %EXPORT_TAGS hash.

If you still want this, I suggest: (untested)

# ... our %EXPORT_TAGS = ( all => [@EXPORT_OK], ); $EXPORT_TAGS{private} = _add_private(); # ...

The %EXPORT_TAGS initialization is split into two statements to ensure a sequence point and avoid a possible undefined evaluation order. This ensures that the initial @EXPORT_OK is copied into a new array before _add_private modifies its contents.

Replies are listed 'Best First'.
Re^4: Importing multiple %EXPORT_TAGS
by stevieb (Canon) on Dec 28, 2020 at 04:44 UTC

    Great catch!

    However, the separation isn't needed. As soon as I saw you put the EXPORT_OK into an anonymous array, changed from the taking of the reference as I had it, I realized that's all that was needed. So all now instead of being a reference to the array, it's a reference to a copy of it:

    our %EXPORT_TAGS = ( all => [ @EXPORT_OK ], private => _export_private(), ); sub _export_private { push @EXPORT_OK, @EXPORT_PRIVATE; return \@EXPORT_OK; }

    Output:

    $VAR1 = { 'private' => [ 'add_bugtracker', 'add_repository', 'changes', 'changes_bump', 'changes_date', 'ci_badges', 'ci_github', 'git_ignore', 'init', 'make_test', 'manifest_skip', 'move_distribution_files', 'remove_unwanted_files', 'version_bump', 'version_info', '_git_commit', '_git_push', '_validate_git' ], 'all' => [ 'add_bugtracker', 'add_repository', 'changes', 'changes_bump', 'changes_date', 'ci_badges', 'ci_github', 'git_ignore', 'init', 'make_test', 'manifest_skip', 'move_distribution_files', 'remove_unwanted_files', 'version_bump' 'version_info', ] };

      I am fairly sure the separation is needed, unless you can point to documentation somewhere that says the values used to initialize a hash will always be evaluated left-to-right. Otherwise, your code may work now, but is relying on undefined behavior and may stop working in a future version of perl.

      The problem is that _export_private modifies @EXPORT_OK, so the order in which [@EXPORT_OK] and _export_private() are evaluated matters. If the list values are evaluated right-to-left in some future version of perl, you will be right back where you were, as the internal functions will be added to @EXPORT_OK just before the array is copied for the :all tag.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11125849]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (1)
As of 2024-04-25 02:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found