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

Sorry this is a complete newbie question (and I probably don't even have the terminology correct), but I have been searching for the past hour for this anwswer and am completely lost.
$response = $ua->get($url); if (not ($response->is_success)) { die "Can't retrieve $url\n"; } if ($response->filename !~ /$regex/) { die "Can't get name of file from header.\n"; } else { open ( FILE, '>', $response->filename ) or die "Can't open file for writing.\n"; print FILE $response->content; close FILE or die "Can't close file.\n"; print "Saved data to $response->filename\n\n"; }
All works well (even the tests) except for the last line. I get:
Saved data to HTTP::Response=HASH(0x29e79e0)->filename
How do I access that variable (and why is it different inside of the print statement)?

Replies are listed 'Best First'.
Re: Addressing object variables
by BrowserUk (Patriarch) on Sep 03, 2010 at 13:28 UTC

    Use:

    print "Saved data to ", $response->filename, "\n\n"; ## or printf "Saved data to %s\n\n", $response->filename; ## or print "Saved data to " . $response->filename . "\n\n"; ## or (though you'll be condemned for doing it:) print "Saved data to ${ \$response->filename }\n\n";
    (and why is it different inside of the print statement)?

    It isn't "different inside a print statement". It is different inside a double-quoted string.

    Perl usefully interpolates (replaces) recognisable variable names with their current values inside double-quoted strings. But method calls aren't values, they are code execution. To obtain the value you have to run the code, and that'd be more like eval than interpolation.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Addressing object variables
by FunkyMonk (Bishop) on Sep 03, 2010 at 13:20 UTC
    How do I access that variable
    By not quoting it:
    print "Saved data to ", $response->filename, "\n\n";

    (and why is it different inside of the print statement)
    As I said, because it's inside quotes.
Re: Addressing object variables
by Anonymous Monk on Sep 03, 2010 at 13:23 UTC

    Variables like "$response" in double quotes are interpolated. That's why you see "HTTP::Response=HASH(0x29e79e0)" in your output; it is printing your reference.

    Check out perlreftut, and note that in order to look up a key in a hash, you need curly brackets around the key.

    IE: $response->{content}

Re: Addressing object variables
by pemungkah (Priest) on Sep 03, 2010 at 22:28 UTC
    Note that since you can (but perhaps shouldn't) do this:
    print "saved data to @{ [ $response->filename ] }\n";
    This takes advantage of two things:
    1. Embedding an array in a quoted string causes the elements to all be interpolated, with the default array separator between them (set to one space when your script starts, but changeable if you like).
    2. Putting a method call inside an anonymous list constructor calls the method in list context and then uses the returned value(s) to create the anonymous array.
    So what @{ [ $obj->method ] } does is
    1. Call the method, getting a list of zero or more values back
    2. Produce a reference to an anonymous array
    3. Immediately dereference the array reference, producing an array consisting of the values returned from the method
    4. Interpolate the array into the string, thereby embedding the return values from the method call into the string
    Why would you not do that? Well, it's not exactly straightforward, to start with, and there's a perfectly reasonable way to do it without the arcane interpolation. I have used it on occasion when it improved readability, but it's probably not a good habit to get in to.