disappearing arguments when one package function calls another

Discussion in 'Perl Misc' started by wana, Oct 16, 2004.

  1. wana

    wana Guest

    I am packaging a set of commonly used functions to make my code a
    little more easy to read. I called a package function with another
    package function and the arguments I passed to it were not in @_ as
    expected. I imagine if I passed by reference it might work or maybe I
    need to use an array global to the package instead of @_, but those
    solutions will take away from the simplicity I was hoping for. My
    background is in C++ where this would be a normal way of doing things.
    I found the chapter on symbol tables and packages in Programming Perl
    to be a little confusing, but I thought that's where the answer would
    be.


    Here's the package (with irrelevant code removed). The problem comes
    up when ReplaceInFile('one','two','file1','file2') calls LoadFromFile.
    LoadFromFile does not receive any of the passed arguments.

    package myfunctions
    ..
    ..
    ..
    sub LoadFromFile
    #takes array reference and file name as argument
    #and clears array and fills array with file contents
    {
    my ($array, $filename) = @_;
    open my $file, '<', $filename or die "Couldn't open $filename:
    $!";
    @{$array} = <$file>;
    close $file or die "Error closing $filename: $!";
    }
    ..
    ..
    ..
    sub ReplaceInFile
    {
    #parameters
    my $target = shift; #string to search for to replace
    my $source = shift; #string to replace with
    my $infile = shift;
    my $outfile = shift;

    #private variables
    my @workspace;

    LoadFromFile(@workspace,$infile);
    foreach(@workspace) {s/$target/$source/g;}
    SaveToFile(@workspace,$outfile);
    }
    1;


    Thanks!

    wana
    wana, Oct 16, 2004
    #1
    1. Advertising

  2. wana wrote:

    > sub LoadFromFile
    > #takes array reference and file name as argument
    > #and clears array and fills array with file contents
    > {
    > my ($array, $filename) = @_;


    But you're not passing it a reference. In C++ terms, you're using
    pass-by-value here:

    > LoadFromFile(@workspace,$infile);


    To pass a reference to @workspace, you want to do this:

    LoadFromFile(\@workspace, $infile);

    sherm--

    --
    Cocoa programming in Perl: http://camelbones.sourceforge.net
    Hire me! My resume: http://www.dot-app.org
    Sherm Pendley, Oct 16, 2004
    #2
    1. Advertising

  3. wana

    Paul Lalli Guest

    wana wrote:
    > I am packaging a set of commonly used functions to make my code a
    > little more easy to read. I called a package function with another
    > package function and the arguments I passed to it were not in @_ as
    > expected. I imagine if I passed by reference it might work or maybe I
    > need to use an array global to the package instead of @_, but those
    > solutions will take away from the simplicity I was hoping for.


    No they wouldn't. You would be adding exactly one character of code to
    pass the array by reference, as it should be.


    > package myfunctions
    > .
    > .
    > .
    > sub LoadFromFile
    > #takes array reference and file name as argument
    > #and clears array and fills array with file contents


    You claim this function takes an array refernece.....

    > {
    > my ($array, $filename) = @_;
    > open my $file, '<', $filename or die "Couldn't open $filename:
    > $!";
    > @{$array} = <$file>;
    > close $file or die "Error closing $filename: $!";
    > }
    > .
    > .
    > .
    > sub ReplaceInFile
    > {
    > #parameters
    > my $target = shift; #string to search for to replace
    > my $source = shift; #string to replace with
    > my $infile = shift;
    > my $outfile = shift;
    >
    > #private variables
    > my @workspace;
    >
    > LoadFromFile(@workspace,$infile);


    ....But here you pass the function an empty list followed by $infile. If
    you want LoadFromFile() to modify the array, you must pass a reference
    to the array. Otherwise, you are only passing the contents of the array:

    LoadFromFile(\@workspace, $infile);

    > foreach(@workspace) {s/$target/$source/g;}
    > SaveToFile(@workspace,$outfile);
    > }
    > 1;


    Note that alternatively, you could provide LoadFromFile a prototype that
    would specify the arguments it needs to receive:

    sub LoadFromFile(\@$) {
    #...
    }

    This would have the effect of automatically creating a reference to the
    array passed in (so no further changes would be required to either your
    LoadFromFile, nor to ReplaceInFile as you had written it).

    Paul Lalli
    Paul Lalli, Oct 16, 2004
    #3
  4. wana

    Ben Morrow Guest

    Quoth (wana):
    >
    > package myfunctions


    All-lowercase top-level package names are reserved for pragmas. Chose
    another name, either MyFunctions or (preferably) something more
    descriptive.

    > @{$array} = <$file>;


    There's no need for these {}, @$array will work perfectly well. Of
    course, it does no harm to leave them in if you find it easier to follow
    like that.

    > sub ReplaceInFile
    > {
    > #parameters
    > my $target = shift; #string to search for to replace
    > my $source = shift; #string to replace with
    > my $infile = shift;
    > my $outfile = shift;


    It would be easier to write

    my ($target, $source, $infile, $outfile) = @_;

    although it will not have quite the same effect (the arguments will not
    be removed from @_; in this case it makes no difference).

    > foreach(@workspace) {s/$target/$source/g;}


    This is very bad style. If you want a one-line for loop, use a statement
    modifier:

    s/$target/$source/g for @workspace;

    .. Otherwise, write it properly:

    for (@workspace) {
    s/$target/$source/g;
    }

    Ben

    --
    Although few may originate a policy, we are all able to judge it.
    - Pericles of Athens, c.430 B.C.
    Ben Morrow, Oct 18, 2004
    #4
    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. jmborr
    Replies:
    1
    Views:
    397
    Stargaming
    Nov 3, 2007
  2. David Mathog
    Replies:
    23
    Views:
    614
    CBFalconer
    Aug 5, 2008
  3. Ravi
    Replies:
    6
    Views:
    319
  4. Adam
    Replies:
    19
    Views:
    2,316
    Richard Bos
    Aug 14, 2010
  5. Bob
    Replies:
    5
    Views:
    247
Loading...

Share This Page