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

To the beseeched,

I wish to return a glob from a sub and use that glob as a form of a call in an expression. I am wrestling with the syntax. Here is what I am expecting success to look like:

sub retg { ... return *var }

then,

${retg} = ... (possibly) $retg = ... (maybe) or even $foo = $retg (I don't know)

In other words, I wish to call retg within the expression and then do the appropriate "cast" to and use that variable.

Much thanks.


NOT P IMPLIES P IMPLIES Q

Replies are listed 'Best First'.
Re: Returning and using a glob from a sub.
by BrowserUk (Patriarch) on Dec 13, 2014 at 01:22 UTC

    This covers most of what you might want of put into a glob (though there are a few other obscure possibilities: io handles and formats):

    Perl> *it = \'"1..4"';; Perl> *it = [ 1 .. 4 ];; Perl> *it = { 1 .. 4 };; Perl> *it = sub{ say '?1..4?'; };; Perl> sub getIt{ return *it };; Perl> $g = getIt();; Perl> say ${ $g };; "1..4" Perl> say @{ $g };; 1 2 3 4 Perl> say %{ $g };; 1 2 3 4 Perl> &{ $g };; ?1..4?

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Returning and using a glob from a sub.
by BrowserUk (Patriarch) on Dec 12, 2014 at 23:41 UTC

    Perl> sub it{ say 'hi' };; Perl> sub getIt{ return *it; };; Perl> my $glob = getIt(); $glob->();; hi Perl> getIt()->();; hi

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Returning and using a glob from a sub.
by runrig (Abbot) on Dec 12, 2014 at 23:45 UTC
    Must..ask..WHY? Can you write and explain a clear example (pseudocode if necessary) of what you're really trying to do? And explain why you want to do it?
Re: Returning and using a glob from a sub.
by LanX (Saint) on Dec 12, 2014 at 23:51 UTC
    Your question is quite cryptic!

    Do you want to alias to the returned package var?

    DB<144> $x=42 => 42 DB<145> sub retg { *x } DB<146> *y= ret() DB<147> $y => 42 DB<148> $y=666 => 666 DB<149> $x => 666

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re: Returning and using a glob from a sub.
by LanX (Saint) on Dec 13, 2014 at 00:17 UTC
    or do you want to alter the stash slot holding the glob?

    I think in this case you need to return a reference to a glob and dereference it with *

    DB<101> $a=42 => 42 DB<102> sub ret_gr { \*a } DB<103> $b=666 => 666 DB<105> *{ret_gr()}=*b DB<106> $a # *a is now an alias of *b => 666 DB<107> $b => 666 DB<108> $a=0 => 0 DB<109> $b => 0

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re: Returning and using a glob from a sub. (lvalue sub)
by LanX (Saint) on Dec 13, 2014 at 15:31 UTC
    My first idea was using lvalue subs, but it didn't work in the debugger REPL so I thought this might not work ... ( bug?¹ )

    Trying to find out why revealed that it works pretty well from a source file.

    script:

    use strict; use warnings; use Data::Dump; $\="\n"; our $x='X'; our $y='Y'; our (@x,@y,@z); # return lvalue glob sub lg :lvalue { *x }; print '--- make $x alias of $y' ; lg=\$y; dd \*x; print '$x= ',"'$x'"; $y='YY'; print '$x= ',"'$x'"; print '--- make *x alias of *z' ; lg=*z; dd \*x; our $z='Z'; print '$x= ',"'$x'"; @z=qw(Z ZZ ZZZ); print '@x= ',"qw/@x/";

    output:

    --- make $x alias of $y do { my $a = \*main::x; *{$a} = \"Y"; *{$a} = []; $a; } $x= 'Y' $x= 'YY' --- make *x alias of *z do { my $a = \*main::z; *{$a} = []; $a; } $x= 'Z' @x= qw/Z ZZ ZZZ/

    UPDATE

    output from Data::Dump seems correct... globs are just confusing

    UPDATE

    changed dd *a to dd \*a to make output of Data::Dump less confusing

    UPDATE

    ²) not a bug, just a problem with my debugger settings!

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re: Returning and using a glob from a sub.
by mephtu (Novice) on Dec 26, 2014 at 22:20 UTC

    Thank you one and all for your concise responses. I am sorry if I was a bit unclear and less than speedy in responding to the posts. I should have made my intentions clear; I don't have much experience with asking questions in a public forum like this one.

    Essentially, I am creating a simple class, consisting of a constructor and an a method. The argument to the constructors sets the value of the datum, while the sub grants access to the datum.

    I wanted to get around using explicit accessor and mutator methods and simply have a subroutine which, with a little syntactic sugar, could be used as a variable. I know, it sounds insane. Ne'ertheless, I shan't delve into my madness here.

    My thinking, as unclear as it may seem, led me to believe a glob value could serve this dual purpose if one derefernced it properly:

    package datum; our $value = undef; sub new { my $class = shift; local $value = shift; return bless { datum => $value, glob => *value }, $class } sub value { my $self = shift; return $self{glob} } 1

    This "wants" to have the effect of returning an alias for the datum when used in a manner similar to the following:

    use datum; my $d = datum->new(42); *d = $d->value(); # What I want to be able to here is something like: # $d = ...; $d->{foo} = ...; push @d, ...

    Perhaps, this makes things a little more clear. Thank you in advance.

    NOT P IMPLIES P IMPLIES Q
      I wanted to get around using explicit accessor and mutator methods and simply have a subroutine which, with a little syntactic sugar, could be used as a variable.

      Then you should take a look at Lvalue subroutines.

      By way of example here are a couple of classes that use lvalue method ->item():

      package Vector { sub new{ my $class = shift; bless [ map{ int() == 0+$_ ? int() : d +ie( "'$_' not an integer in Vector::new" ) } @_ ], $class } sub item :lvalue { $_[0]->[ $_[1] ] } 1; } package Matrix { sub new { my $class = shift; bless [ map{ ref() eq 'Vector' ? $_ : + die "'$_' not a Vector in Matrix::new" } @_ ], $class } sub item :lvalue { $_[0]->[ $_[1] ]->item( $_[2] ); } sub mmMxN { use integer; my( $self, $other ) = @_; die "Incompatible matrix dimensions" unless @{ $self } == @{ $ +other->[0] }; my $return = Matrix->new( map Vector->new( (0) x @{ $self } ), + 0 .. $#{ $other->[ 0 ] } ); for my $i ( 0 .. $#{ $self } ) { for my $j ( 0 .. $#{ $other->[0] } ) { $return->item( $i, $j ) += $self->item( $i, $_ ) * $ot +her->item( $_, $j ) for 0 .. $#{ $other }; } } return $return; } 1; }

      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
      your question has already been answered, you have to pass references.

      But the code you are showing has too many issues.

      this doesn't make sense since $value is localized and will be deleted after new() returns.

      sub new { my $class = shift; local $value = shift; return bless { datum => $value, glob => *value }, $class }
      the only "slot" holding the value is $obj->{datum}

      then be aware that $self is supposed to hold an object (i.e. blessed hashref), you have to deref $self properly

      sub value { my $self = shift; # return $self{glob} # will never work return $self->{glob} # might work }

      finally this is nonsense, you can't use a glob sigil with a private variable my $d

      my $d = datum->new(42); *d = $d->value();

      your alias must be a package var.

      If you really want to go on with shortcuts, why not simply try a scalar ref?

      my $datum = \ $obj->{datum}; # and then $$datum = ...;

      > # $d->{foo} = ...; push @d, ...

      well hashes and arrays must be refs anyway...

      so you'll need to write things like

      $datum->{foo}=...; push @$datum,...;

      But plz be aware that you are now committing crimes against many laws of OOP!

      Cheers Rolf

      (addicted to the Perl Programming Language and ☆☆☆☆ :)

      for completeness this kind of aliasing to hash elements works, even if the hash itself is a lexical variable.

      DB<121> $self->{a} = [1..3] => [1, 2, 3] DB<122> *a = $self->{a} DB<123> @a => (1, 2, 3) DB<124> @a=6..8 => (6, 7, 8) DB<125> $self->{a} => [6, 7, 8]

      so if you only store references in your objects hash (including scalar refs) then you can return them from a value() sub.

      be sure to localize the global aliases you'll use then.

      our ($datum,@datum,%datum); # chose whatever you want local *datum= value("datum");

      Cheers Rolf

      (addicted to the Perl Programming Language and ☆☆☆☆ :)