Different array length depending on whether it is returned from a subroutine

Discussion in 'Perl Misc' started by paulburton0@gmail.com, Mar 28, 2013.

  1. Guest

    This script is for a very basic web api client that I'm making. The server returns json and I'm using JSON:XS to decode that to native perl data structures. My problem is that I'm having trouble with an array that I'm returning from a subroutine. If I do not return the array (or arrayref), I can print all the elements of the array using foreach. If I *do* return the array (or arrayref), only one element is added to the array. See annotated code below. (Unfortunately, this code won't run as-is because API access requiresOAuth details that I can't share.) I'm hoping that there's an idiosyncrasyin perl (or huge stupid mistake that I'm not seeing) that someone can point out just looking at the code. I've seen similar questions asked elsewhere, but there's never a satisfactory answer (if any).

    [... head of script snipped (oauth details, module declarations, etc.) ...]
    sub fetch_likes{

    my $offset = shift;

    my $r;

    if ($offset){

    $r = $ua->get("http://api.tumblr.com/v2/user/likes?limit=20&offset=$offset");

    }else{

    $r = $ua->get("http://api.tumblr.com/v2/user/likes?limit=20");
    }

    my $response = $r->content();

    my $json = JSON::XS->new->decode ($response);

    my $likes = ${$json}{'response'}{'liked_posts'};

    return $likes; # This is an arrayref
    }

    sub get_image_urls{

    # This function expects a reference to an array containing liked posts.
    # Such a reference is returned from fetch_likes()

    my $likes = shift;

    foreach (@$likes) {

    my $photos = ${$_}{'photos'};

    my @urls; # This initializes the array that I want to return.

    foreach (@$photos){

    push (@urls, ${$_}{'original_size'}{'url'}); # Populate the array
    }

    foreach (@urls){ # This prints every element in the array (20 or so),
    print; # but *only* of the 'return' line below is commented
    print"\n";
    }

    return \@urls; # Return the array reference. If this is uncommented,
    # the foreach immediately above it will only output one
    # array element. Behavior is the same if it's not a
    # reference
    }
    }

    # Main

    my $ref_to_likes = fetch_likes();
    my $ref_to_urls = get_image_urls($ref_to_likes);

    foreach (@$ref_to_urls){ # This block behaves exactly like the one in
    # the get_image_urls sub, depending on whether
    # the return of that sub is commented or not.
    print;
    print "\n";
    }
    , Mar 28, 2013
    #1
    1. Advertising

  2. writes:

    [...]

    > my $likes = ${$json}{'response'}{'liked_posts'};


    A general remark: Perl has (meanwhile and since a while) a
    dereferencing operator. And the {} automatically quote arguments which
    are 'simple idenifiers'. Considering both, the line above could be
    written as

    my $likes = $json->{response}{liked_posts}

    eliminating some of the 'line noise' characters.

    >
    > sub get_image_urls{
    >
    > # This function expects a reference to an array containing liked posts.
    > # Such a reference is returned from fetch_likes()
    >
    > my $likes = shift;
    >
    > foreach (@$likes) {
    >
    > my $photos = ${$_}{'photos'};
    >
    > my @urls; # This initializes the array that I want to return.
    >
    > foreach (@$photos){
    >
    > push (@urls, ${$_}{'original_size'}{'url'}); # Populate the array
    > }
    >
    > foreach (@urls){ # This prints every element in the array (20 or so),
    > print; # but *only* of the 'return' line below is commented
    > print"\n";
    > }
    >
    > return \@urls; # Return the array reference. If this is uncommented,
    > # the foreach immediately above it will only output one
    > # array element. Behavior is the same if it's not a
    > # reference
    > }
    > }


    You didn't per chance mean to place the return \@urls after the outer
    foreach loop? With the code as it is quoted here, only the first
    element in @$likes will ever be processed because the subroutine
    returns at the end of the first iteration of the outer loop.
    Rainer Weikusat, Mar 28, 2013
    #2
    1. Advertising

  3. Paul Burton Guest

    On Thursday, March 28, 2013 4:25:16 PM UTC-4, Rainer Weikusat wrote:

    > You didn't per chance mean to place the return \@urls after the outer
    >
    > foreach loop? With the code as it is quoted here, only the first
    >
    > element in @$likes will ever be processed because the subroutine
    >
    > returns at the end of the first iteration of the outer loop.


    That was it. I just lost track of curly braces I guess. Thanks a lot for the second pair of eyes on this. And thanks to everyone who replied for the stylistic/practical tips as well.
    Paul Burton, Mar 29, 2013
    #3
    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. joanne matthews (RRes-Roth)
    Replies:
    9
    Views:
    277
  2. Kit
    Replies:
    0
    Views:
    333
  3. xyoavx

    subroutine's returned value

    xyoavx, Dec 2, 2005, in forum: Perl Misc
    Replies:
    2
    Views:
    56
    xyoavx
    Dec 2, 2005
  4. king
    Replies:
    5
    Views:
    173
  5. newfie912
    Replies:
    2
    Views:
    143
Loading...

Share This Page