Using "Perl Best Practices" inside-out objects

Discussion in 'Perl Misc' started by mhearne808[insert-at-sign-here]gmail[insert-dot-he, May 15, 2007.

  1. All: I'm having trouble returning an array from a class implemented
    using Damian Conway's inside-out object approach.

    Below are two snippets of code:
    1) The test script where I am attempting to retrieve an array from an
    inside-out attribute from an object.
    2) The test class.

    I think the main problem is on the line where I am assigning an array
    to one of these inside out attributes. Somehow I think the attribute
    is only getting the last element of the array that I am attempting to
    assign it to.

    I would have tested Conway's code verbatim, except that the
    File::System->list_files() method in his text does not seem to exist.
    I assume from context that list_files() returns an array of files...

    Does anyone have (simple) examples of inside-out classes with a method
    that returns an array?

    #Test script
    use PAGER::Test;
    use strict;

    my $test = PAGER::Test->new();
    my @array = $test->getData();
    my $n;
    foreach $n (@array){
    print "$n\n";
    }
    #end of test script

    #Test module
    #!/usr/bin/perl

    package MYPACKAGE::Test;
    use Class::Std::Utils;
    use strict;
    {
    my %data; #the absolute path where pager.pl is located

    sub new{
    my ($class) = @_;
    my $new_object = bless anon_scalar(),$class;
    $data{ident $new_object} = (1,2,3,4,5);
    return $new_object;
    }

    sub getData{
    my ($self) = @_;
    return @{$data{ident $self}};
    }

    sub DESTROY{
    my ($self) = @_;
    delete $data{ident $self};
    return;
    }
    }
    1;
    #end of Test module
    mhearne808[insert-at-sign-here]gmail[insert-dot-he, May 15, 2007
    #1
    1. Advertising

  2. mhearne808[insert-at-sign-here]gmail[insert-dot-he

    Paul Lalli Guest

    On May 15, 3:17 pm, "mhearne808[insert-at-sign-here]gmail[insert-dot-
    here]com" <> wrote:
    > All: I'm having trouble returning an array from a class implemented
    > using Damian Conway's inside-out object approach.
    >
    > Below are two snippets of code:
    > 1) The test script where I am attempting to retrieve an array from an
    > inside-out attribute from an object.
    > 2) The test class.
    >
    > I think the main problem is on the line where I am assigning an array
    > to one of these inside out attributes. Somehow I think the attribute
    > is only getting the last element of the array that I am attempting to
    > assign it to.


    I snipped the class structure, because inside-out objects have nothing
    at all to do with this problem. Giant Red Herring. The problem is
    this line:

    $data{ident $new_object} = (1,2,3,4,5);

    If you print $data{ident $new_object}, you will see it contains the
    value 5. That is because you cannot assign a list of values to a
    scalar. What you're actually doing is using the comma operator in
    scalar context. (see perldoc perlop for more info on that).

    Instead, you need to assign a reference to an anonymous array to that
    scalar value. The construct for creating such a reference is square
    brackets, not parentheses.

    $data{ident $new_object} = [ 1, 2, 3, 4, 5];

    Once again, this has nothing to do with objects, be they 'normal' or
    inside-out. This is the same issue as if you had errantly done:

    my $foo = (1, 2, 3, 4, 5);
    In that case, $foo would get the value 5. Whereas if you'd correctly
    done:
    my $foo = [1, 2, 3, 4, 5];
    then $foo would get a reference to an anonymous array that contains
    the values (1, 2, 3, 4, 5).

    Hope this helps,
    Paul Lalli
    Paul Lalli, May 15, 2007
    #2
    1. Advertising

  3. Paul - Thanks very much! I didn't know about the [] syntax for
    creating references to arrays. I presume now that the mythical
    list_files() method returns a reference to an array, not an array.
    Might have been helpful if Conway had used a real method in his
    example.

    --Mike

    On May 15, 1:35 pm, Paul Lalli <> wrote:
    > On May 15, 3:17 pm, "mhearne808[insert-at-sign-here]gmail[insert-dot-
    >
    > here]com" <> wrote:
    > > All: I'm having trouble returning an array from a class implemented
    > > using Damian Conway's inside-out object approach.

    >
    > > Below are two snippets of code:
    > > 1) The test script where I am attempting to retrieve an array from an
    > > inside-out attribute from an object.
    > > 2) The test class.

    >
    > > I think the main problem is on the line where I am assigning an array
    > > to one of these inside out attributes. Somehow I think the attribute
    > > is only getting the last element of the array that I am attempting to
    > > assign it to.

    >
    > I snipped the class structure, because inside-out objects have nothing
    > at all to do with this problem. Giant Red Herring. The problem is
    > this line:
    >
    > $data{ident $new_object} = (1,2,3,4,5);
    >
    > If you print $data{ident $new_object}, you will see it contains the
    > value 5. That is because you cannot assign a list of values to a
    > scalar. What you're actually doing is using the comma operator in
    > scalar context. (see perldoc perlop for more info on that).
    >
    > Instead, you need to assign a reference to an anonymous array to that
    > scalar value. The construct for creating such a reference is square
    > brackets, not parentheses.
    >
    > $data{ident $new_object} = [ 1, 2, 3, 4, 5];
    >
    > Once again, this has nothing to do with objects, be they 'normal' or
    > inside-out. This is the same issue as if you had errantly done:
    >
    > my $foo = (1, 2, 3, 4, 5);
    > In that case, $foo would get the value 5. Whereas if you'd correctly
    > done:
    > my $foo = [1, 2, 3, 4, 5];
    > then $foo would get a reference to an anonymous array that contains
    > the values (1, 2, 3, 4, 5).
    >
    > Hope this helps,
    > Paul Lalli
    mhearne808[insert-at-sign-here]gmail[insert-dot-he, May 15, 2007
    #3
  4. mhearne808[insert-at-sign-here]gmail[insert-dot-he

    Paul Lalli Guest

    On May 15, 3:44 pm, "mhearne808[insert-at-sign-here]gmail[insert-dot-
    here]com" <> wrote:
    >
    > On May 15, 1:35 pm, Paul Lalli <> wrote:
    >
    > > On May 15, 3:17 pm, "mhearne808[insert-at-sign-here]gmail[insert-dot-

    >
    > > here]com" <> wrote:
    > > > All: I'm having trouble returning an array from a class implemented
    > > > using Damian Conway's inside-out object approach.

    >
    > > > Below are two snippets of code:
    > > > 1) The test script where I am attempting to retrieve an array from an
    > > > inside-out attribute from an object.
    > > > 2) The test class.

    >
    > > > I think the main problem is on the line where I am assigning an array
    > > > to one of these inside out attributes. Somehow I think the attribute
    > > > is only getting the last element of the array that I am attempting to
    > > > assign it to.

    >
    > > I snipped the class structure, because inside-out objects have nothing
    > > at all to do with this problem. Giant Red Herring. The problem is
    > > this line:

    >
    > > $data{ident $new_object} = (1,2,3,4,5);

    >
    > > If you print $data{ident $new_object}, you will see it contains the
    > > value 5. That is because you cannot assign a list of values to a
    > > scalar. What you're actually doing is using the comma operator in
    > > scalar context. (see perldoc perlop for more info on that).

    >
    > > Instead, you need to assign a reference to an anonymous array to that
    > > scalar value. The construct for creating such a reference is square
    > > brackets, not parentheses.

    >
    > > $data{ident $new_object} = [ 1, 2, 3, 4, 5];

    >
    > > Once again, this has nothing to do with objects, be they 'normal' or
    > > inside-out. This is the same issue as if you had errantly done:

    >
    > > my $foo = (1, 2, 3, 4, 5);
    > > In that case, $foo would get the value 5. Whereas if you'd correctly
    > > done:
    > > my $foo = [1, 2, 3, 4, 5];
    > > then $foo would get a reference to an anonymous array that contains
    > > the values (1, 2, 3, 4, 5).


    > Paul - Thanks very much! I didn't know about the [] syntax for
    > creating references to arrays.


    You need to review a bunch of perliminary Perl information before you
    start tackling objects (of any flavor). Please pause for a few
    minutes and read:
    perldoc perlreftut
    perldoc perllol
    perldoc perldsc

    > I presume now that the mythical
    > list_files() method returns a reference to an array, not an array.


    Not necessarily. You can return an array from a subroutine just fine.

    sub foo {
    my $ref = [ 1, 2, 3, 4, 5 ];
    return @{$ref};
    }

    my @stuff = foo();

    > Might have been helpful if Conway had used a real method in his
    > example.


    I have no idea what "example" you're talking about. Can you give a
    pointer to it? Is it in PBP? What chapter/page? Or is it online
    somewhere?

    Paul Lalli
    Paul Lalli, May 15, 2007
    #4
  5. >>>>> "PL" == Paul Lalli <> writes:

    PL> You need to review a bunch of perliminary Perl information

    Great typo!

    Charlton


    --
    Charlton Wilbur
    Charlton Wilbur, May 15, 2007
    #5
  6. On 15 May 2007 16:04:47 -0400, Charlton Wilbur
    <> wrote:

    > PL> You need to review a bunch of perliminary Perl information
    >
    >Great typo!


    I (tend to) do it all the time. In Italian 'for' is 'per' and can be
    followed by a word beginning with 'l', typically a determinative
    article. Imagine what happens when I write "per la miseria!"


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, May 15, 2007
    #6
  7. mhearne808[insert-at-sign-here]gmail[insert-dot-he

    Peter Scott Guest

    On Tue, 15 May 2007 12:35:18 -0700, Paul Lalli wrote:
    > On May 15, 3:17 pm, "mhearne808[insert-at-sign-here]gmail[insert-dot-
    > here]com" <> wrote:
    >> All: I'm having trouble returning an array from a class implemented
    >> using Damian Conway's inside-out object approach.
    >>
    >> Below are two snippets of code:
    >> 1) The test script where I am attempting to retrieve an array from an
    >> inside-out attribute from an object.
    >> 2) The test class.
    >>
    >> I think the main problem is on the line where I am assigning an array
    >> to one of these inside out attributes. Somehow I think the attribute
    >> is only getting the last element of the array that I am attempting to
    >> assign it to.

    >
    > I snipped the class structure, because inside-out objects have nothing
    > at all to do with this problem. Giant Red Herring.

    [snip]

    So is the implementation. I presume the OP is working through PBP, but
    they may be unaware that they've only reached an intermediate stage of
    inside-out object construction and that Conway is working toward using his
    CPAN module Class::Std, where it won't be necessary for the user to write
    a new() method, accessors, or destructor. Then an implementation of an
    array-based attribute looks like:

    #!perl
    use strict;
    use warnings;

    package Foo;

    use Class::Std;

    my %thing :ATTR( :name<thing> :default<[]> );

    sub things {
    my $self = shift;
    @{ $self->get_thing };
    }

    package main;

    my $foo = Foo->new( { thing => [ qw(a b c) ] } );

    print "$_\n" for $foo->things;
    __END__

    But as you later point out, the OP may need to master some more basic
    concepts first.

    --
    Peter Scott
    http://www.perlmedic.com/
    http://www.perldebugged.com/
    Peter Scott, May 16, 2007
    #7
  8. On Wed, 16 May 2007 09:45:59 GMT, Peter Scott <> wrote:

    >my %thing :ATTR( :name<thing> :default<[]> );


    I briefly heard about attributes, and I know I could read the docs,
    but I hadn't seen that syntax yet: that is, angular parens. When were
    they introduced? Where are they documented? (I know about their use in
    Perl 6, but that's a whole another story.)


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, May 16, 2007
    #8
  9. mhearne808[insert-at-sign-here]gmail[insert-dot-he

    Paul Lalli Guest

    On May 16, 5:45 am, Peter Scott <> wrote:
    > use Class::Std;
    >
    > my %thing :ATTR( :name<thing> :default<[]> );


    I'm 99% sure that doesn't work, as I tried it (albeit with standard
    Perl 5 syntax) only last week. The default attribute can only take
    strings. Array refs don't work. You need to provide a BUILD
    subroutine in which you assign name to [].

    Paul Lalli
    Paul Lalli, May 16, 2007
    #9
  10. mhearne808[insert-at-sign-here]gmail[insert-dot-he

    Peter Scott Guest

    On Wed, 16 May 2007 04:35:29 -0700, Paul Lalli wrote:
    > On May 16, 5:45 am, Peter Scott <> wrote:
    >> use Class::Std;
    >>
    >> my %thing :ATTR( :name<thing> :default<[]> );

    >
    > I'm 99% sure that doesn't work, as I tried it (albeit with standard
    > Perl 5 syntax) only last week. The default attribute can only take
    > strings. Array refs don't work. You need to provide a BUILD
    > subroutine in which you assign name to [].


    Well it works for me :)

    % cat foo
    #!/usr/local/bin/perl
    use strict;
    use warnings;

    package Foo;
    use Class::Std;

    my %thing :ATTR( :name<thing> :default<[3..5]> );

    sub things {
    my $self = shift;
    @{ $self->get_thing };
    }

    package main;

    my $foo = Foo->new;
    print "$_\n" for $foo->things;
    __END__

    % ./foo
    3
    4
    5

    % perl -MClass::Std -le 'print VERSION Class::Std'
    0.000008

    --
    Peter Scott
    http://www.perlmedic.com/
    http://www.perldebugged.com/
    Peter Scott, May 18, 2007
    #10
  11. mhearne808[insert-at-sign-here]gmail[insert-dot-he

    Peter Scott Guest

    On Wed, 16 May 2007 12:53:20 +0200, Michele Dondi wrote:
    > On Wed, 16 May 2007 09:45:59 GMT, Peter Scott <> wrote:
    >
    >>my %thing :ATTR( :name<thing> :default<[]> );

    >
    > I briefly heard about attributes, and I know I could read the docs,
    > but I hadn't seen that syntax yet: that is, angular parens. When were
    > they introduced? Where are they documented? (I know about their use in
    > Perl 6, but that's a whole another story.)


    perldoc Class::Std. They're completely peculiar to that module, because
    it's parsing the argument of :ATTR itself. Parens and guillemots work
    also, and fat comma syntax. Look in the source at the subroutine
    _extractor_for_pair_named().

    --
    Peter Scott
    http://www.perlmedic.com/
    http://www.perldebugged.com/
    Peter Scott, May 18, 2007
    #11
  12. Paul Lalli <> wrote:

    > You can return an array from a subroutine just fine.



    No you can't.


    > sub foo {
    > my $ref = [ 1, 2, 3, 4, 5 ];
    > return @{$ref};
    > }
    >
    > my @stuff = foo();



    You can return the _contents_ of an array (a list) from a
    subroutine just fine.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, May 18, 2007
    #12
  13. On Fri, 18 May 2007 12:40:31 GMT, Peter Scott <> wrote:

    >>>my %thing :ATTR( :name<thing> :default<[]> );

    >>
    >> I briefly heard about attributes, and I know I could read the docs,
    >> but I hadn't seen that syntax yet: that is, angular parens. When were
    >> they introduced? Where are they documented? (I know about their use in
    >> Perl 6, but that's a whole another story.)

    >
    >perldoc Class::Std. They're completely peculiar to that module, because
    >it's parsing the argument of :ATTR itself. Parens and guillemots work
    >also, and fat comma syntax. Look in the source at the subroutine
    >_extractor_for_pair_named().


    I kinda understand: but then what's in the "argument" to an attribute
    is considered a plain string, that can be parsed at one's will?


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, May 18, 2007
    #13
  14. mhearne808[insert-at-sign-here]gmail[insert-dot-he

    Paul Lalli Guest

    On May 18, 8:30 am, Peter Scott <> wrote:
    > On Wed, 16 May 2007 04:35:29 -0700, Paul Lalli wrote:
    > > On May 16, 5:45 am, Peter Scott <> wrote:
    > >> use Class::Std;

    >
    > >> my %thing :ATTR( :name<thing> :default<[]> );

    >
    > > I'm 99% sure that doesn't work, as I tried it (albeit with standard
    > > Perl 5 syntax) only last week. The default attribute can only take
    > > strings. Array refs don't work. You need to provide a BUILD
    > > subroutine in which you assign name to [].

    >
    > Well it works for me :)
    >
    > % cat foo
    > #!/usr/local/bin/perl
    > use strict;
    > use warnings;
    >
    > package Foo;
    > use Class::Std;
    >
    > my %thing :ATTR( :name<thing> :default<[3..5]> );
    >
    > sub things {
    > my $self = shift;
    > @{ $self->get_thing };
    >
    > }
    >
    > package main;
    >
    > my $foo = Foo->new;
    > print "$_\n" for $foo->things;
    > __END__
    >
    > % ./foo
    > 3
    > 4
    > 5
    >
    > % perl -MClass::Std -le 'print VERSION Class::Std'
    > 0.000008


    Apparently it's only the Perl5 syntax that doesn't allow it. Changing
    your line above to:
    my %thing :ATTR( name => 'thing', default => [3..5] );

    results in:
    Missing initializer label for Foo: 'thing'.
    Fatal error in constructor call at ./foo.pl line 18

    $ perl -MClass::Std -le 'print VERSION Class::Std'
    0.000008

    Paul Lalli
    Paul Lalli, May 18, 2007
    #14
  15. mhearne808[insert-at-sign-here]gmail[insert-dot-he

    Peter Scott Guest

    On Fri, 18 May 2007 15:27:04 +0200, Michele Dondi wrote:
    > On Fri, 18 May 2007 12:40:31 GMT, Peter Scott <> wrote:
    >>> I briefly heard about attributes, and I know I could read the docs,
    >>> but I hadn't seen that syntax yet: that is, angular parens. When were
    >>> they introduced? Where are they documented? (I know about their use in
    >>> Perl 6, but that's a whole another story.)

    >>
    >>perldoc Class::Std. They're completely peculiar to that module, because
    >>it's parsing the argument of :ATTR itself. Parens and guillemots work
    >>also, and fat comma syntax. Look in the source at the subroutine
    >>_extractor_for_pair_named().

    >
    > I kinda understand: but then what's in the "argument" to an attribute
    > is considered a plain string, that can be parsed at one's will?


    Oh yes. perldoc attributes. Class::Std is using the native,
    complicated way of parsing attributes directly rather than a helper module
    like Attribute::Handlers. Look at MODIFY_type_ATTRIBUTES. In the case of
    Class::Std programs, the type is HASH, and there is only one attribute in
    the list, called 'ATTR'. Read further down: "...The parameter list is
    passed as it was found, however..."

    --
    Peter Scott
    http://www.perlmedic.com/
    http://www.perldebugged.com/
    Peter Scott, May 19, 2007
    #15
  16. On Sat, 19 May 2007 12:44:19 GMT, Peter Scott <> wrote:

    >Oh yes. perldoc attributes. Class::Std is using the native,
    >complicated way of parsing attributes directly rather than a helper module
    >like Attribute::Handlers. Look at MODIFY_type_ATTRIBUTES. In the case of


    TY


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, May 19, 2007
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. nobody
    Replies:
    1
    Views:
    524
    Venkatesh
    Apr 26, 2006
  2. kj
    Replies:
    0
    Views:
    70
  3. Replies:
    9
    Views:
    174
    Anno Siegel
    Jan 19, 2006
  4. Replies:
    7
    Views:
    162
    Salvador Fandino
    May 5, 2006
  5. Koszalek Opalek
    Replies:
    16
    Views:
    224
    Koszalek Opalek
    Mar 18, 2008
Loading...

Share This Page