in reply to Re: Net::DNS answer count
in thread Net::DNS answer count

So I got the code to work by doing the following:

Is there a better way to do this with the code originally posted?

my $query = $resolver->query($target_ip, 'PTR'); my @answer = $query->answer; print "Total # of Hostnames found: ", scalar(@answer), "\n";

Replies are listed 'Best First'.
Re^3: Net::DNS answer count
by kcott (Archbishop) on Apr 10, 2023 at 06:37 UTC
    "Is there a better way to do this with the code originally posted?"

    In essence, no.

    You want the value of @answer in the loop just after reporting the count, so it makes sense to assign 'my @answer =' once and then reuse the value.

    If you're asking specifically about the print statement, what you have is fine. There are multiple ways of doing this and, for the most part, it would come down to personal style more than anything else. I tend to favour '0+@array' over 'scalar(@array)'; but that's just me. Here's a handful of different ways you could do this:

    $ perl -E ' my @answers = qw{x y z}; say "Total: ", scalar(@answers); say "Total: ", 0+@answers; say "Total: @{[scalar @answers]}"; say "Total: @{[0+@answers]}"; ' Total: 3 Total: 3 Total: 3 Total: 3

    [See "discussion of @{[...]}" (from a few days ago) if you're unfamiliar with that construct.]

    In the main, your code is fine.

    There's one subtlety of which few are aware (or fully understand) — don't feel too bad about this slip-up by yourself. :-)

    The loop variable in a for loop is lexically scoped to that loop. Other references to variables of the same name outside the loop are different variables. Consider these (and note that I had to turn off strict for demonstration purposes):

    $ perl -E ' #use strict; use warnings; { my $i; for $i (1,2,3) { say $i; } say $i // "undefined"; } { for my $i (1,2,3) { say $i; } say $i // "undefined"; } { for $i (1,2,3) { say $i; } say $i // "undefined"; } { my $i = q{completely different $i}; for $i (1,2,3) { say $i; } say $i // "undefined"; } ' 1 2 3 undefined 1 2 3 undefined 1 2 3 undefined 1 2 3 completely different $i

    With strict enabled, the $i outside the loop is problematic:

    $ perl -E ' use strict; use warnings; for my $i (1,2,3) { say $i; } say $i // "undefined"; ' Global symbol "$i" requires explicit package name (did you forget to d +eclare "my $i"?) at -e line 9. Execution of -e aborted due to compilation errors.

    There is an anomaly with this. I consider it to be a bug in Perl and probably the cause of much confusion. If you don't declare the loop variable with my, strict complains:

    $ perl -E ' use strict; use warnings; for $i (1,2,3) { say $i; } ' Global symbol "$i" requires explicit package name (did you forget to d +eclare "my $i"?) at -e line 5. Global symbol "$i" requires explicit package name (did you forget to d +eclare "my $i"?) at -e line 6. Execution of -e aborted due to compilation errors.

    unless you've previously declared a different variable with the same name with my in an outer scope:

    $ perl -E ' use strict; use warnings; my $i; for $i (1,2,3) { say $i; } say $i // "undefined"; ' 1 2 3 undefined

    Declaration after the loop still raises an error with the loop variable:

    $ perl -E ' use strict; use warnings; for $i (1,2,3) { say $i; } my $i; say $i // "undefined"; ' Global symbol "$i" requires explicit package name (did you forget to d +eclare "my $i"?) at -e line 5. Global symbol "$i" requires explicit package name (did you forget to d +eclare "my $i"?) at -e line 6. Execution of -e aborted due to compilation errors.

    Here's a very quick review of the remainder; bear in mind that much of this comes down to style as opposed to corrections:

    • Using a plural for arrays generally reads better: $answer vs. @answers. Also, @answer could be a simple typo but strict won't pick up that you really meant $answer.
    • Although $object->method is valid syntax, $object->method() is clearer in my opinion.
    • You generally want chomp instead of chop.
    • Don't bother chomping when the next line is print (now requiring that the newline be added back again). In other words, don't write all of this:
      chomp $line; print $line, "\n";

      when this would've sufficed:

      print $line;
    • for and foreach are synonymous. Using the former promotes (good) laziness.
    • Consistent code layout improves readability. What you have isn't terrible; although, I do see indentations of 2, 4, 5 & 8 characters.

    — Ken

      Thank you kindly for your reply sir!