Re: question about variables from new perl user
by GrandFather (Saint) on Dec 01, 2015 at 00:04 UTC
|
Actually the documentation says it returns ($content_type, $document_length, $modified_time, $expires, $server) so I'd write:
my ($content_type, $document_length, $modified_time, $expires, $server
+) = head($url);
If you want that as a hash instead (Perl for "associative array") you could:
my %head;
@head{qw(content_type document_length modified_time expires server)} =
+ head($url);
die "Unable to get page '$url'\n" if !defined $head{content};
which uses a hash slice to initialize the key/value pairs. Note the % sigil which tells the viewer that head returns a hash. Access the fields like:
my $modified_time = $head{modified_time};
Now see that we use a $ sigil to show that head{modified_time} returns a scalar value. The sigil ($, @, % or &) tells you what type of thing the expression returns. See perldata for extensive documentation on Perl's data structures and variable naming etc.
Premature optimization is the root of all job security
| [reply] [d/l] [select] |
Re: question about variables from new perl user
by kcott (Archbishop) on Dec 01, 2015 at 02:38 UTC
|
G'day rst,
Welcome to the Monastery.
"Note, this question is about the particular code snippet, ..."
The responses you've received so far, appear to have covered most aspects of this.
I would just add, that when you find yourself coding lists of sequentially numbered variables, take a step back and reconsider your approach. You probably don't need to write that much code but, more importantly, what you're writing is very error-prone.
Even with the few lines you have here, it's completely unclear what any of the $tN variables actually refer to.
While it may be fairly easy, from the context of initialisation, to determine what, say, $t3 holds;
finding $t3 by itself, a screen or two later, won't be at all helpful: you'll probably need to scroll back to the initialisation code to determine what data it holds.
It's also far too easy, with a typical typo caused by accidentally hitting a key adjacent to the one you want, to type $t2 or $t4 instead of $t3. When eyeballing the code, this won't immediately leap out at you as a mistake and, given they're all valid variables, Perl probably won't be in a position to alert you to the problem.
It's quite likely that you'll end up with a bug that's hard to track down.
There's an even more subtle problem here.
Array indices in Perl are zero-based while your sequential numbering starts at one.
So, it's not intuitively obvious whether $t3 was the 3rd or 4th value returned: back to scrolling again.
GrandFather has shown improvements with both meaningfully named variables and hash keys.
Here's another way with meaningfully named array indices.
use constant {
CONTENT_TYPE => 0,
DOCUMENT_LENGTH => 1,
...
};
...
my @head_values = head(...);
...
# later in the code far from the initialisation
... $head_values[DOCUMENT_LENGTH] ...
You now have $head_values[DOCUMENT_LENGTH] which is fairly clear and obvious.
Furthermore, even not-so-obvious typos (e.g. $head_values[DOCUMENT_LEMGTH]) will be picked up by Perl at compile time, assuming you've used the strict pragma (which you should always use).
"... but even more it is about understanding variables in Perl."
I suggest you start by reading "perlintro -- a brief introduction and overview of Perl".
This manpage isn't long and, given "I'm new to perl, but not programing", should not present you with any difficulties.
While I recommend you read it in its entirety, the "Perl variable types" and "Variable scoping" sections most closely answer what you're asking today.
The great thing about this piece of documentation is that it's peppered with numerous links to more detailed information and advanced topics.
Get the foundation knowledge first then follow the links for greater enlightenment.
| [reply] [d/l] [select] |
|
|
Thanks for the suggestion to RTFM, always a good suggestion :)
Especially good when accompanied with a link. And yes, I got lazy and wrote messy code even though I know better. Sorry. Can I ask if you have any good cures for Laziness, or would that be a new topic, and I would have to start a new thread? ;)
| [reply] |
|
|
Hello rst, and welcome to the Monastery!
Can I ask if you have any good cures for Laziness, ...?
Actually, there are two kinds of laziness, a good kind and a bad kind, and the good kind is the cure for the bad kind! Perl’s creator, Larry Wall, famously said:
We will encourage you to develop the three great virtues of a programmer: laziness, impatience, and hubris.
— Programming Perl, First Edition (see, e.g., here)
The perlglossary defines the good kind of laziness as follows:
laziness
The quality that makes you go to great effort to reduce overall energy expenditure. It makes you write labor-saving programs that other people will find useful, and then document what you wrote so you don’t have to answer so many questions about it. Hence, the first great virtue of a programmer....
You can think of it as long-term laziness (efficiency — the good kind) vs. short-term laziness (cutting corners, the bad kind). Take the long-term view and you will want to learn best practices. Inevitably, you’ll then develop good programming habits; soon, you’ll be writing idiomatic, efficient, and effective Perl. Win-win!
Update: Corollary:
Hlade’s Law: If you have a difficult task, give it to a lazy man — he will find an easier way to do it.
— (In)Famous Laws; see also naChoZ’s homenode
Hope that helps,
| [reply] |
Re: question about variables from new perl user
by Apero (Scribe) on Nov 30, 2015 at 23:54 UTC
|
If you want to get details like the Server header-value (assuming the server you got the reply from set it) you're going to need the full-featured OO LWP class, perhaps by inspecting an object within the HTTP::Headers class that can return arbitrary headers from a successful request.
The LWP::Simple class is a functional-Perl (sometimes called just FP) library that hides the "complex" class details. The return value of LWP::Simple::head() is documented to return a TRUE value on success (and while it is not formally documented, it seems to return undef on failure, which evaluates to false in a boolean context.)
Update: as GrandFather pointed out, you can certainly name your variables, or even stuff them into a hash. I think OP was asking about accessing the "hashref" (which the API says is a boolean) returned in scalar context. For an intro to scalar vs array context, this tutorial may be of use. /Update.
What you're seeing when you call Data::Dumper::Dumper() on the return value is actually a Perl object (see the perlobj docs) which just happens to evaluate to TRUE in boolean context. According to the API, you're not supposed to consider whatever else comes back (although traditionally a true boolean reply is simply the value 1, but clearly isn't always going to be as evident here.)
I would strongly advise you to avoid relying on the content you get in the hashref returned by the FP class methods unless they explicitly document returning an object of a particular class. In this case, it appears the returned object is of the class HTTP::Response, but per the API, there's no reason to believe this will be forward-compatible or will remain a stable access method.
Hopefully this clears up the confusion on the volumes of data you see; you're effectively looking at the object's internal structure, and it's generally unwise to rely on (or certainly edit!) an object's structure; exceptions to this can include if you're creating a subclass, or simply willing to accept that you're relying on a "private" part of the class. Perl won't stop you from playing with what C++ or Java programmers might call "private" class/method variables, but it's simply best not to.
| [reply] [d/l] [select] |
Re: question about variables from new perl user
by choroba (Cardinal) on Nov 30, 2015 at 23:15 UTC
|
Perl is not PHP. Associative arrays use curly braces:
$temp{headers}{etag}
Square brackets are for arrays.
Disclaimer: I'm not saying it will work for your problem.
($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
| [reply] [d/l] [select] |
Re: question about variables from new perl user
by Cristoforo (Curate) on Dec 01, 2015 at 01:01 UTC
|
Looking through LWP::Simple, LWP and lwpcook, I couldn't find documentation on accessor methods but found that some methods were available (through experimentation :-) ). I've documented some of them in the code below.
#!/usr/bin/perl
use strict;
use warnings;
use LWP::Simple;
my $req = head("http://perlmonks.com"); # request
if ($req) {
print "protocol:\n\t",
$req->protocol, "\n";
print "headers->etag:\n\t",
$req->headers->{etag}, "\n";
# a leading underscore is considered 'private'
# and probably should not be accessed
print "_rc:\n\t",
$req->{_rc}, "\n";
print "request->uri:\n\t",
$req->request->uri, "\n";
print "request->headers->{'user-agent'}:\n\t",
$req->request->headers->{'user-agent'}, "\n";
}
Output was:
protocol:
HTTP/1.1
headers->etag:
"e047-525cb6d2fef00"
_rc:
200
request->uri:
http://perlmonks.com
request->headers->{'user-agent'}:
LWP::Simple/6.00 libwww-perl/6.02
| [reply] [d/l] [select] |
|
|
I couldn't find documentation on accessor methods
Right, because a True/False boolean value does not have methods. The fact that LWP::Simple::head() returns an object is an undocumented side-effect as the API is described. Do not rely on this to be an object (and thus do not rely on any data in the object, object methods, accessors, and so on.)
As I commented on earlier, I ventured a guess this class returned an object out of simplicity or convenience. The LWP::Simple class docs, however, are very clear that you get a "TRUE" (sic) value back from the function call. It's highly unwise to use it as a constructor.
If you want to know what type an object is (and can't otherwise tell from documentation, which is where you should go to look for that fact,) you can do so with the ref() built-in call, like so:
require LWP::Simple;
my $fake_boolean = LWP::Simple::head( "http://google.com" );
printf "fake_boolean variable is a reference to: %s\n",
ref($fake_boolean) || "<not-a-reference>";
Big fat warning: do not use this function's return as an object! This is merely a demonstration of how to determine an object's type. Please refer to the LWP documentation on how the object-oriented class is designed and what constructors return what types of objects to avoid unpleasant surprises later.
| [reply] [d/l] [select] |
|
|
Thank you everybody,
choroba, it takes a little bit of time to wrap my mind around the idea that an array with with numerical indices and one with alphanumeric indices are different. None of C/C++ and PHP are like that. I will have to get used to that.
Apero and Grandfather, thank you for the explanation of what is going on , the right way to do things, and the warnings.
Cristoforo, thank you for your insight. sometimes you learn a lot from breaking the rules. (and sometimes you learn fire is hot and it can burn ;) )
Thanks again,
Ray
| [reply] |
|
|