in reply to Re: Invoke sub whose name is value of scalar
in thread Invoke sub whose name is value of scalar

There's usually better ways of achieving one's goals. We could help you better if we knew what you were actually trying to do.

I have used symbolic references to simulate linked lists. For example:

sub _create_node { my ($node,$parent,$node_info) = @_; no strict; @{$node}{qw/parent info/} = ($parent,$node_info); }

This way, each node is a hash with the name of its parent under the key "parent" and the info related to the node under the key "node_info". To go through a node:

sub go_through { no strict 'refs'; my ($self, $node) = @_; return "" unless defined ${$node}{"info"}; my @info_nodes; while (${$node}{"info"} ne "root"){ push @info_nodes, (${$node}{"info"}); $node = ${$node}{"parent"}; } return \@info_nodes; }

This runs very fast and doesn't need too much memory

citromatik

Replies are listed 'Best First'.
Re^3: Invoke sub whose name is value of scalar
by dragonchild (Archbishop) on Apr 14, 2008 at 13:55 UTC
    Except that's not a symbolic reference. That's a hash-reference and your code is more commonly written as:
    sub go_through { my ($self, $node) = @_; return unless defined $node->{info}; my @info_nodes; while ( $node->{info} ne 'root' ) { push @info_nodes, $node->{info}; $node = $node->{parent}; } return \@info_nodes; }
    This version also fixes a bug you had in your original code regarding contexts.

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

      I don't know if you have understand correctly my snippet. Here is a working example to clarify:

      use strict; use warnings; use Data::Dumper; _create_node ("p1","pp1","first"); _create_node ("pp1","ppp1","second"); _create_node ("ppp1","pppp1","third"); _create_node ("pppp1","ppppp1","root"); my $infos = _go_through("p1"); print Dumper $infos; sub _create_node { my ($node,$parent,$node_info) = @_; no strict 'refs'; @{$node}{qw/parent info/} = ($parent,$node_info); } sub _go_through { no strict 'refs'; my ($node) = @_; return "" unless defined ${$node}{"info"}; my @info_nodes; while (${$node}{"info"} ne "root"){ push @info_nodes, (${$node}{"info"}); $node = ${$node}{"parent"}; } return \@info_nodes; }

      Outputs:

      $VAR1 = [ 'first', 'second', 'third' ];

      We can argue if this use of symbolic references is a correct strategy or not, but I hope that we agree that they ARE symbolic references

      Your subroutine using the arrow notation works as well, excepts that you need to switch off strict-ness:

      sub _go_through { no strict 'refs'; my ($node) = @_; return unless defined $node->{info}; my @info_nodes; while ( $node->{info} ne 'root' ) { push @info_nodes, $node->{info}; $node = $node->{parent}; } return \@info_nodes; }

      Or you will get pretty

      Can't use string ("p1") as a HASH ref while "strict refs" in use at .. +.

      citromatik

        Remove the no strict 'refs'; in both subroutines and try the following:
        my $root = {}; _create_node( $root, 'pp1', 'first' ); _create_node( $root->{pp1}, 'ppp1', 'second' ); # And so forth

        You were forcing your code to use symbolic references. Intrinsically, it wasn't doing so. In other words, the code didn't look like it forced the use of symbolic references. It was only your usage of it that was forcing it to do so. And, by doing it my way, you will avoid some really nasty, hard-to-find bugs.


        My criteria for good software:
        1. Does it work?
        2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?