dereferencing in perl

U

Uno

$ perl client5.pl
command: GROUP comp.lang.perl.misc
result(211): 4777 658225 663028 comp.lang.perl.misc
658225 663028
663023

....

command: XHDR message-id 663028
result(221): message-id fields follow
received 1 lines
ARRAY(0x85a7a98)
command: QUIT
result(205): .
$ cat client5.pl
#!/usr/bin/perl
use strict;
use warnings;
use Net::NNTP ();
require
my $group = 'comp.lang.perl.misc';
my $server = 'News.Individual.NET';
my $USER = '';
my $PASS = '';

my $c = new $c->authinfo($USER, $PASS);
$c->debug(2);
my ($first, $last) = ($c->group($group));
print "$first $last \n";

for (my $i = ($last -5); $i <= $last; $i++) {
print "$i \n";
my $subject = $c->xhdr("", $i);
print "$subject\n";

}
__END__
$

I have a tried a million things to see the contents of the array as
opposed to reference and give up. Suggestions?
 
M

Marc Girod

I have a tried a million things to see the contents of the array as
opposed to reference and give up.  Suggestions?

I got neither which array, nor what exactly you tried so far, so,
let's start simple:

$ perl -le '$qq=[qw(a b c)]; print $qq; print for @{$qq}'
ARRAY(0x816db50)
a
b
c

Marc
 
M

Marc Girod

But I have to think.

I cannot connect to that server, so that I cannot reproduce.
Not sure what output comes from the debug info.
So, I give up.
Sorry again for the noise.
Marc
 
M

Marc Girod

M

Marc Girod

I found an nntp I didn't know inside Ericsson!

Oh! And now that I started to read the man page, sorry to say that you
shot yourself in the foot.
The following works (in replacement for you whole loop):

print $c->xhdr("", $last-5, $last);

I.e. print does 'the right thing', as documented.
You just prevent it from happening by forcing a scalar context,
as you assign the result to a variable.

Marc
 
U

Uno

print $_ for @{$subject};

$ perl client6.pl
command: GROUP comp.lang.perl.misc
result(211): 4770 658251 663046 comp.lang.perl.misc
658251 663046
663041
command: XHDR Subject 663041
result(221): Subject fields follow
received 1 lines
663041 Re: dereferencing in perl
663041 Re: dereferencing in perl
Use of uninitialized value $d in concatenation (.) or string at
client6.pl line 23, <SOCK1> line 7.

....

command: QUIT
result(205): .
$ cat client6.pl
#!/usr/bin/perl
use strict;
use warnings;
use Net::NNTP ();
require
my $group = 'comp.lang.perl.misc';
my $server = 'News.Individual.NET';
my $USER = '';
my $PASS = '';

my $c = new $c->authinfo($USER, $PASS);
$c->debug(2);
my ($first, $last) = ($c->group($group));
print "$first $last \n";

for (my $i = ($last -5); $i <= $last; $i++) {
print "$i \n";
my $subject = $c->xhdr("Subject", $i);
print $_ for @{$subject};
my $d = print $_ for @{$subject};
print "$d\n";
}
__END__

$

So, thx, marc, I'm able to move forward, but what I need is to have the
line you gave me stored as a variable.
my $d = print $_ for @{$subject};
was my best attempt and looks like it may have worked, but it drew an
exception and is an obvious kludge.
 
U

Uno

Oh! And now that I started to read the man page, sorry to say that you
shot yourself in the foot.
The following works (in replacement for you whole loop):

print $c->xhdr("", $last-5, $last);

I.e. print does 'the right thing', as documented.
You just prevent it from happening by forcing a scalar context,
as you assign the result to a variable.

Marc

Marc, I think the reason that I'm "forcing" scalar context is that I
need the entire control to be something I can understand. Hence the
traditional for.

Again, I need a variable here, but beyond that I wanted to discuss this
context, because, from my point of view, scalar context is forcing
itself on me.

I thought this excerpt from cpan for might contain
something relevant:

xhdr

Fetch header for a range of articles. First argument is name of
header to fetch. If omitted or blank, default to Message-ID. Second
argument is start of article range. If omitted, defaults to 1. Third
argument is end of range. If omitted, defaults to "". The second
argument can also be a Message-ID.

Returns headers as an array of lines terminated by the current EOL.

In scalar context a reference to the array is returned instead of
the array itself.

Examples:

# Fetch Message-ID of article 1.
$c->xhdr();

# Fetch Subject of article 1.
$c->xhdr("Subject");

# Fetch Subject of article 3345.
$c->xhdr("Subject", 3345);

# Fetch Subjects of articles 3345-9873
$c->xhdr("Subject", 3345, 9873);

# Fetch Message-ID of articles 3345-9873
$c->xhdr("", 3345,9873);

# Fetch Subject for article with Message-ID
$c->xhdr("Subject", '<[email protected]>');
 
J

J. Gleixner

Uno wrote:
[...]
So, thx, marc, I'm able to move forward, but what I need is to have the
line you gave me stored as a variable.
my $d = print $_ for @{$subject};
No.

was my best attempt and looks like it may have worked, but it drew an
exception and is an obvious kludge.

That's because it's wrong.

You either want to 'push' $subject onto an array you can use later,
and iterate over it, as needed, or possibly use join, if you want
to combine multiple elements of the @$subject into a scalar.

Most would probably stick with an array, since you probably want
some sort of order, later.
for (my $i = ($last -5); $i <= $last; $i++) {

^^^^ That's pretty ugly.

my @combined;
for my $i ( $last-5 .. $last )
{
push( @combined, $c->xhdr("Subject", $i) );
}

for my $item ( @$combined )
{
for my $subitem ( @$item )
{
print ">>$subitem\n";
}
}

For help with data structures, e.g. an AoA, read/study: perldoc perldsc
 
U

Uno

Uno wrote:
That's because it's wrong.

You either want to 'push' $subject onto an array you can use later,
and iterate over it, as needed, or possibly use join, if you want
to combine multiple elements of the @$subject into a scalar.

Most would probably stick with an array, since you probably want
some sort of order, later.


^^^^ That's pretty ugly.

my @combined;
for my $i ( $last-5 .. $last )
{
push( @combined, $c->xhdr("Subject", $i) );
}

for my $item ( @$combined )
{
for my $subitem ( @$item )
{
print ">>$subitem\n";
}
}

For help with data structures, e.g. an AoA, read/study: perldoc perldsc

$ perl client6.pl

....
module/library search path?

command: QUIT
result(205): .
$ cat client6.pl
#!/usr/bin/perl
use strict;
use warnings;
use Net::NNTP ();
require
my $group = 'comp.lang.perl.misc';
my $server = 'News.Individual.NET';
my $USER = '';
my $PASS = '';

my $c = new $c->authinfo($USER, $PASS);
$c->debug(2);
my @combined;
my ($first, $last) = ($c->group($group));
for my $i ( $last-5 .. $last )
{
push( @combined, $c->xhdr("Subject", $i) );
}

for my $item ( @combined )
{
for my $subitem ( $item )
{
print ">>$subitem\n";
}
}
__END__

Alright, thx J, this is useful to me, even if it's not the direction I
want to go. It occurs to me after reading perldoc perldsc that arrays
of arrays are not the direction I want to go, that indeed I want to
force there to be scalar context.

So I'm back at the beginning again.

my $subject = $c->xhdr("", $i);
print "$subject\n";

Is there no way shorter way to what I intend other than having to create
an array and populate it with push? I frankly still don't understand
why this original formulation only shows the references. and not the
contents.
 
U

Uno

So I'm back at the beginning again.

my $subject = $c->xhdr("", $i);
print "$subject\n";

Is there no way shorter way to what I intend other than having to create
an array and populate it with push? I frankly still don't understand why
this original formulation only shows the references. and not the contents.

sub xhdr {
@_ >= 2 && @_ <= 4 or croak 'usage: $nntp->xhdr( HEADER, [
MESSAGE-SPEC ] )';
my $nntp = shift;
my $hdr = shift;
my $arg = _msg_arg(@_);

$nntp->_XHDR($hdr, $arg)
? $nntp->_description
: undef;
}

I think I got it. I think this is the definition of xhdr which I found
in NNTP.pm. Once I saw the definition of xhdr, I think I made the
appropriate change:

$ perl client7.pl
command: GROUP comp.lang.perl.misc
result(211): 4742 658286 663053 comp.lang.perl.misc
command: XHDR Subject 663048
result(221): Subject fields follow
received 1 lines
663048 Re: dereferencing in perl

command: XHDR Subject 663049
result(221): Subject fields follow
received 1 lines
663049 Re: dereferencing in perl

command: XHDR Subject 663050
result(221): Subject fields follow
received 1 lines
663050 C callbacks returning a value

command: XHDR Subject 663051
result(221): Subject fields follow
received 1 lines
663051 FAQ 8.48 How do I add the directory my program lives in to the
module/library search path?

command: XHDR Subject 663052
result(221): Subject fields follow
received 1 lines
663052 Re: C callbacks returning a value

command: XHDR Subject 663053
result(221): Subject fields follow
received 1 lines
663053 Re: dereferencing in perl

command: QUIT
result(205): .
$ cat client7.pl
#!/usr/bin/perl
use strict;
use warnings;
use Net::NNTP ();
require
my $group = 'comp.lang.perl.misc';
my $server = 'News.Individual.NET';
my $USER = '';
my $PASS = '';

my $c = new $c->authinfo($USER, $PASS);
$c->debug(2);
my ($first, $last) = ($c->group($group));
for my $i ( $last-5 .. $last ){
my ($subject, undef) = $c->xhdr("Subject", $i);
print "$subject\n";
}
__END__


$
 
J

J. Gleixner

Why do you care how many lines it takes?

After reading through the documentation, xhdr can take a range, which is
why it returns a list or reference to one or more elements. If you
want to flatten it, then use join.
sub xhdr {
@_ >= 2 && @_ <= 4 or croak 'usage: $nntp->xhdr( HEADER, [
MESSAGE-SPEC ] )';
my $nntp = shift;
my $hdr = shift;
my $arg = _msg_arg(@_);

$nntp->_XHDR($hdr, $arg)
? $nntp->_description
: undef;
}

I think I got it. I think this is the definition of xhdr which I found
in NNTP.pm. Once I saw the definition of xhdr, I think I made the
appropriate change:

Hmmmm.. Looking at _XHDR and _description would be needed, the above
doesn't really show anything useful. Also, your class is
so that's where you want to look, if you
feel the source code is more helpful than the documentation.

#!/usr/bin/perl
use strict;
use warnings;
use Net::NNTP ();
^^^^ Why is this class being used?
require News::NNTPClient;
^^^^^ Why require??
my $group = 'comp.lang.perl.misc';
my $server = 'News.Individual.NET';
my $USER = '';
my $PASS = '';
^^^^^^^ Why are these uppercase, and the others aren't? Be
consistent.
my $c = new News::NNTPClient($server);
Using $news, or something more descriptive, will be better than $c.

my $news = $server );
$c->authinfo($USER, $PASS);
$c->debug(2);
my ($first, $last) = ($c->group($group));
for my $i ( $last-5 .. $last ){
my ($subject, undef) = $c->xhdr("Subject", $i);
print "$subject\n";
}

Since you know the range, just make one call, and get all subjects:

my $subj_aref = $news->xhdr("Subject", $last-5, $last );

Then do whatever you want with that aref.

Print each subject, one by one:

for my $subject ( @$subj_aref )
{
print $subject, "\n";
}

Flatten it:

my $all_subjects = join("\n", @$subj_aref );

and then print it:

print $all_subjects, "\n";

Typically, there's no need to combine it, since you
can call join when/if that's needed.

print join("\n", @$subj_aref ), "\n"

Leaving it as an array/array reference, will let you sort it, do
something with specific elements, figure out how many elements
there are, etc. all of the powerful functions that having an
array provides.

I have no idea what you want to do. If all you want is to
print the subjects, to STDOUT, then you've already seen
many ways to do it, so why keep posting the same question and
the same code?

It doesn't really matter how you do it or how many lines it takes,
as long as you understand it. Usually there's a lot more that
someone wants to do in a program and keeping it as an array
reference will be more useful.
 
U

Uno

Because he is new to programming, and neophytes always think
that that is bettter for some reason.

$ perl client8.pl
command: GROUP comp.lang.perl.misc
result(211): 4711 658334 663070 comp.lang.perl.misc
command: XHDR Subject 663068
result(221): Subject fields follow
received 1 lines
663068 List of valid HTML friendly mime types

Use of uninitialized value $arg1 in concatenation (.) or string at
client8.pl line 19, <SOCK1> line 7.

command: XHDR Subject 663069
result(221): Subject fields follow
received 1 lines
663069 FAQ 4.58 How do I look up a hash element by value?

Use of uninitialized value $arg1 in concatenation (.) or string at
client8.pl line 19, <SOCK1> line 10.

command: XHDR Subject 663070
result(221): Subject fields follow
received 1 lines
663070 FAQ 4.40 What is the difference between $array[1] and @array[1]?

Use of uninitialized value $arg1 in concatenation (.) or string at
client8.pl line 19, <SOCK1> line 13.

command: QUIT
result(205): .
$ cat client8.pl
#!/usr/bin/perl
use strict;
use warnings;
use Net::NNTP ();
require
my $group = 'comp.lang.perl.misc';
my $server = 'News.Individual.NET';
my $user = '';
my $pass = '';

my $c = new $c->authinfo($user, $pass);
$c->debug(2);
my ($first, $last) = ($c->group($group));
for my $i ( $last-2 .. $last ){
(my $subject, my $arg1) = $c->xhdr("Subject", $i);
print "$subject\n";
print "$arg1\n";
}
__END__


$

Do I succumb to the same criticism if I think "better" is better with
fewer than three t's?:D

Anyways, still looking at xhdr, and this seemed to be the only relevant
stuff in NNTP.pm:

sub xhdr {
@_ >= 2 && @_ <= 4 or croak 'usage: $nntp->xhdr( HEADER, [
MESSAGE-SPEC ] )';
my $nntp = shift;
my $hdr = shift;
my $arg = _msg_arg(@_);

$nntp->_XHDR($hdr, $arg)
? $nntp->_description
: undef;
}

q1) What does perl do when the interpreter sees this?

q2) Why do I not see $arg1 getting populated correctly?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top