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

I am a novice and try to use structs. However, I seem unable to find out how to allocate one. Having spent several hours reading the perl documentation, the Class::Struct documentation and searching the webs, I fearfully decided to approach the sacred halls of Perl Monastery.

Could a fellow monk please help a novice find out how what is wrong with the following script?

use strict; use warnings; use Class::Struct; # include <structs> struct( document => { fileID => '$', # $ = scalar = int filename => '@', # @ = array (of char) = string tags => '@' # tags - array of strings }); # all of these three attempts to allocate memory fail: #my $doc = document->new( ); # produces: Can't locate object metho +d "fileID" via package "doc" (perhaps you forgot to load "doc"?) at t +estsnippet01.pl line 18. #my $doc = new( 'document'); # produces: Undefined subroutine &mai +n::new called at testsnippet01.pl line 12. #my $doc = new( document); # produces: Bareword "document" not a +llowed while "strict subs" in use at testsnippet01.pl line 13. my $doc = <WhatGoesHere?> # Hopefully a Perl saint knows what g +oes here... doc->fileID( 123 ); doc->filename( 'SampleFileName' ); doc->tags( 'tag1', 'tag2', 'tag3' ); print "File ID: ", doc->fileID, "\n"; print "Filename: ", doc->filename, "\n"; print "Tags: ", doc->tags, "\n";

I already looked into the alternative using associative arrays, but it would be much cleaner and effective to use structs like in C for my purposes...

So, any idea what the correct spell to allocate a struct could be?

Replies are listed 'Best First'.
Re: How to allocate a struct?
by Athanasius (Archbishop) on Oct 28, 2014 at 12:23 UTC

    Hello dissident, and welcome to the Monastery!

    The following line caught my eye:

    filename => '@', # @ = array (of char) = string

    The comment suggests you may have a misunderstanding. In C, a string is indeed an array of char (i.e., characters). But in Perl, a string is a scalar, not an array. So if you want a single filename, you should say:

    filename => '$',

    By the way, you might also want to have a look at MooX::Struct by the Monastery’s own tobyink.

    Update: For example:

    use strict; use warnings; use MooX::Struct Document => [ qw($fileID $filename @tags) ]; my $doc = Document[ 123, 'SampleFileName', [ qw(tag1 tag2 tag3) ] ]; printf "File ID: %s\n", $doc->fileID; printf "Filename: %s\n", $doc->filename; printf "Tags: %s\n", join(', ', @{ $doc->tags });

    Output:

    22:52 >perl 1068_SoPW.pl File ID: 123 Filename: SampleFileName Tags: tag1, tag2, tag3 22:52 >

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      First, I want to thank you all for welcoming me!

      I didn't expect to get an answer so quickly when I noticed Loops posted the first answer. I did some experiments with the code Loops corrected for me, mainly trying to replace the constants in the example with variables, as the final content of the struct members are not yet known when the struct is created. But I then ran into new problems trying this... Then I noticed two more replies arrived.

      I think perlron's suggestion to thoroughly read perlreftut, perldata, perldsc and perlvar docs could indeed be the key. By the way, I read the class::struct doc several times, but it leaves open a lot of questions. Maybe the docs mentioned will reveal much insight... At least it could help avoiding things like misunderstanding of strings being arrays Athanasius pointed at...

      I'll also look into Moo instead of class::struct, as suggested by Loops and Athanasius.

      Thank you again! Now I'll have to read a lot more documentation and do more experimenting...

        great to see some good posts on monks
        can i also suggest u do a perldoc -f <builtin_command_name> when u dont want to bother with all the info and just u need a quick reminder.
        try it out its fun
        Do not wait to strike when the iron is hot! Make it hot by striking - WB Yeats
Re: How to allocate a struct?
by Loops (Curate) on Oct 28, 2014 at 12:02 UTC

    Hi there, welcome to the monastery!

    Couple little typos in your code that you can see below. The main one is that you forgot the $ sigil on the doc-> in the print statements:

    use Class::Struct; struct Document => { fileid => '$', filename => '@', tags => '@' }; my $doc = Document->new( fileid => 2, filename => [qw(a b c)], tags => [qw(d e f)] ); print "File ID: ", $doc->fileid, "\n"; print "Filename: ", @{$doc->filename}, "\n"; print "Tags: ", @{$doc->tags}, "\n";

    Having looked at Class::Struct a bit, I can't say there is much here to recommend it anymore. A more current recommendation would be to use Moo (or Moose) for these features and more. Here is a posting from quite some time back from a more seasoned monk with a comparison.

Re: How to allocate a struct?
by perlron (Pilgrim) on Oct 28, 2014 at 12:11 UTC
    Do not be fearful of the monks , they are so amiable
    Here is a working copy of your code.
    First thing to do is read perldoc Class::Struct
    Using an editor with color coding can help u catch trival issues in perl like doc as opposed to $doc.
    you will also be greatly benefitted by reading perldoc perlreftut to understand how references work.
    coming back to perl after many years, i realise the key to understanding a language is through its basic data structures, so perldoc perldata / perldsc and perlvar are your manual until you reach the level of proficiency
    package TestPackage; 2 use strict; 3 use warnings; 4 use Class::Struct; # include <structs> 5 6 struct( document => { 7 fileID => '$', # $ = scalar = int 8 filename => '@', # @ = array (of char) = string 9 tags => '@' # tags - array of strings 10 }); 11 12 # all of these three attempts to allocate memory fail: 13 #my $doc = document->new( ); # produces: Can't locate object m +ethod "fileID" via package "doc" (perhaps you forgot to load "doc"?) +at testsnippet01. pl line 18. 14 #my $doc = new( 'document'); # produces: Undefined subroutine +&main::new called at testsnippet01.pl line 12. 15 #my $doc = new( document); # produces: Bareword "document" n +ot allowed while "strict subs" in use at testsnippet01.pl line 13. 16 17 my $doc = new document; # Hopefully a Perl saint knows what + goes here... 18 19 $doc->fileID( 123 ); 20 $doc->filename( ['SampleFileName'] ); 21 $doc->tags( ['tag1', 'tag2', 'tag3'] ); 22 23 print "File ID: ", $doc->fileID, "\n"; 24 print "Filename: ", $doc->filename->[0], "\n"; 25 print "Tags: ", $doc->tags->[0], "\n";
    Do not wait to strike when the iron is hot! Make it hot by striking - WB Yeats