in reply to Returning and using a glob from a sub.

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

Replies are listed 'Best First'.
Re^2: Returning and using a glob from a sub.
by BrowserUk (Patriarch) on Dec 26, 2014 at 23:04 UTC
    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.
Re^2: Returning and using a glob from a sub.
by LanX (Saint) on Dec 27, 2014 at 00:23 UTC
    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 ☆☆☆☆ :)

Re^2: Returning and using a glob from a sub.
by LanX (Saint) on Dec 27, 2014 at 00:38 UTC
    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 ☆☆☆☆ :)