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

Hello! My problem is that I want to use a struct as a parameter of a subroutine like this:
use Class::Struct; struct ( 'Structname', { value1 => '$', value2 => '$' } ); my $mystruct = new Structname; #here we set value1 and value2 $value = &myfunction($mystruct);
and in mystruct I need to get value1 and value2 of this $mystruct. I tried to do this:
sub myfunction { use strict; use warnings; use Class::Struct; struct ( 'Structname', { value1 => '$', value2 => '$' } ); my $mystruct = new Structname; $mystruct = $ARGV[0]; return $mystruct->value1." ".$mystruct->value2; }

but the error I get is:
function 'new' already defined in package Structname at filename.pl line 3. 3 is the "struct ( 'Structname', ..." line in subroutine file (which is required in main script).

If I remove the line, then the subroutine can't find the value1. I guess I have to tell the subroutine to find the definition of the struct elsewhere instead of redefining it, but I can't seem to understand how to do that.

I tried googling with the error message but didn't find anything helpful.

I am quite new at perl, so there might also be better ways of doing what I'm trying to do. I have one specific struct I'm using in many places and I want to create a outputstring-formatting subroutine for it instead of always rewriting the same code. In reality the struct has more than two values so I'd really like to be able to pass the whole struct as a parameter instead of having to pass each value separately.

Thank you in advance.

Replies are listed 'Best First'.
Re: Error with using structs as subroutine parameters
by almut (Canon) on Jun 08, 2009 at 08:44 UTC
    I guess I have to tell the subroutine to find the definition of the struct elsewhere instead of redefining it

    As the parameter you're passing to that function already is an object (blessed reference), there's no need to tell Perl where to find its definition. It already knows...

    my $mystruct = new Structname; $mystruct = $ARGV[0];

    The second line overwrites the object — thus creating it in the first place seems rather useless.

    Also, I guess you meant $_[0] instead of $ARGV[0].

      When I remove use Class::Struct line, I get a following error: Can't call method "value1" without a package or object reference

      I figured the "new" line might be useless, but when nothing else worked I got desperate and figured that can't at least make things worse.

        Here's an example that hopefully clears up the usage:

        use strict; use warnings; use Class::Struct; struct ( 'Structname', { value1 => '$', value2 => '$' } ); sub myfunction { my $mystruct = shift; # alternatively: my $mystruct = $_[0]; return $mystruct->value1." ".$mystruct->value2; } my $mystruct = new Structname; $mystruct->value1('foo'); $mystruct->value2(42); my $value = myfunction($mystruct); print "$value\n"; # "foo 42"

        (This also works if you put the sub in a separate file that you then require.)

Re: Error with using structs as subroutine parameters
by cdarke (Prior) on Jun 08, 2009 at 09:03 UTC
    You are using $ARGV[0] in your subroutine. That is the first command-line argument to the program, not the parameter to the subroutine. Did you mean that? Arguments are passed into a sub through @_, not @ARGV.

    If not, then use one of the following (TMTOWTDI):
    $mystruct = shift; # defaults to @_ in a sub ($mystruct) = @_; # copies the first element into $mystruct $mystruct = $_[0]; # Ugly, and possibly misleading
      Thanks, this solved the problem. As I feared it was a true noob error after all.
Re: Error with using structs as subroutine parameters
by jethro (Monsignor) on Jun 08, 2009 at 08:56 UTC

    With few exceptions lines like

    use strict; use warnings; use Class::Struct;
    should be listed at the beginning of a file, not inside of subroutines. I'm not sure, but use of a class inside a subroutine might lead to problems because the implied 'require' would create closures instead of sub-subroutines.

      should be listed at the beginning of a file, not inside of subroutines.
      Why? If you only need a module inside the subroutine, keeping the 'use' close to its usage means that if you later on remove the subroutine, you're not left 'using' a module that isn't actually used.
      I'm not sure, but use of a class inside a subroutine might lead to problems because the implied 'require' would create closures instead of sub-subroutines.
      Rubbish. It will not create closures, and Perl doesn't have any concept of "sub-subroutines" (what are they? Really tiny routines?)

        Ok, accepted. I thought this was the same situation as in mod_perl usage where you had to be careful with global variables because mod_perl put everything into its subroutine. I forgot that used modules usually have a package statement at the beginning that should solve the problem

        and Perl doesn't have any concept of "sub-subroutines"

        It is astonishing how easily one is misunderstood on the internet. Naturally perl has no concept of sub-subroutines and that is what I was saying