in reply to Re: Splitting in while loop in thread Splitting in while loop
Nice work, thanks for both your solutions, tybalt89!
Do you understand why mine wasn't working?
Re^3: Splitting in while loop
by kcott (Archbishop) on Oct 07, 2021 at 07:43 UTC
|
G'day tel2,
"... why mine wasn't working?"
I believe you're working on the erroneous assumption that split(/[, ]+/, <DATA>) will assign its result to $_.
That assignment to $_ only occurs in a select number of cases.
From "perlsyn: Compound Statements":
"If the condition expression of a while statement is based on any of a group of iterative expression types then it gets some magic treatment. The affected iterative expression types are readline, the <FILEHANDLE> input operator, ... If the condition expression is one of these expression types, then the value yielded by the iterative operator will be implicitly assigned to $_."
For each of your while iterations, the condition is true three times, once for each DATA line;
however, $_ is not set for any of those iterations.
On the fourth iteration, there are no more DATA lines and the loop ends.
Always add
use strict;
use warnings;
to the top of your code.
In this instance, although it wouldn't give a detailed explanation of the problem as I've provided,
it would have hinted at a starting point for investigating the issue.
| [reply] [d/l] [select] |
|
Thanks for all that, Ken.
I tried adding strict & warnings before opening this question, and I got the errors, but I just didn't realise what was going on, but I understand now. Maybe I should have posted it with strict & warnings included, and asked why I'm getting the errors.
| [reply] |
|
"Maybe I should have posted it with strict & warnings included, and asked why I'm getting the errors."
I concur with ++eyepopslikeamosquito's comments:
that would have been a far better way to deal with this.
Removing those pragmata from your code does not remove whatever problem they reported.
This is basically just putting your head in the sand:
it neither helps you nor helps us to help you.
What you can do is look for the exception message in perldiag.
Admittedly, in this instance, the description for
"Use of uninitialized value %s"
will not be all that helpful, unless you really don't understand that message:
but, as I said earlier, "it would have hinted at a starting point for investigating the issue".
In many cases, however, the expanded explanation in perldiag can be quite enlightening.
Another option you have is to use the diagnostics pragma.
Be aware that this can be somewhat overwhelming and leave you feeling that you're drowning in exception output.
You can get multiple, often large, blocks of text; however, just as a simple example,
consider a typo where you didn't release the shift key quickly enough after typing a "
and ended up typing a : instead of a ; as the next character:
$ perl -Mstrict -Mwarnings -Mdiagnostics -e 'my $x = "X": print "$x\n"
+;'
syntax error at -e line 1, near ""X":"
Execution of -e aborted due to compilation errors (#1)
(F) Probably means you had a syntax error. Common reasons include
+:
A keyword is misspelled.
A semicolon is missing.
A comma is missing.
An opening or closing parenthesis is missing.
An opening or closing brace is missing.
A closing quote is missing.
Often there will be another error message associated with the synt
+ax
error giving more information. (Sometimes it helps to turn on -w.
+)
The error message itself often tells you where it was in the line
+when
it decided to give up. Sometimes the actual error is several toke
+ns
before this, because Perl is good at understanding random input.
Occasionally the line number may be misleading, and once in a blue
+ moon
the only way to figure out what's triggering the error is to call
perl -c repeatedly, chopping away half the program each time to se
+e
if the error went away. Sort of the cybernetic version of 20 ques
+tions.
Uncaught exception from user code:
syntax error at -e line 1, near ""X":"
Execution of -e aborted due to compilation errors.
Also note that the diagnostics pragma is a developer tool; it is not (normally) appropriate for production code.
Remove use diagnostics; (and similar code) when moving from the development to the production environments.
| [reply] [d/l] [select] |
|
> Maybe I should have posted it with strict & warnings included, and asked why I'm getting the errors
Yes!
Even more important, read and understand the basic Perl documentation for the functions you are using.
If your program does not behave the way the Perl documentation says it should, mention that in your question.
For example, the Perl documentation for split says this, yet I am seeing that.
(Based on your question, I don't see how you could have read and understood the documentation for split).
In summary, please read and attempt to understand the Perl documentation
and test your code with strict and warnings before posting.
| [reply] [d/l] [select] |
Re^3: Splitting in while loop
by AnomalousMonk (Archbishop) on Oct 07, 2021 at 07:44 UTC
|
Further to jwkrahn's post: tel2: Note that implicit split to @_ has been deprecated for a long time:
Win8 Strawberry 5.8.9.5 (32) Thu 10/07/2021 3:29:50
C:\@Work\Perl\monks
>perl -Mstrict -Mwarnings
my $data = <<'EOD';
me@here.com
those@there.com others@there.com
you@there.com,them@there.com
EOD
open my $fh, '<', \$data or die "opening: $!";
while (split(/[, ]+/, <$fh>))
{
chomp @_;
print "'$_'\n" for @_;
}
^Z
Use of implicit split to @_ is deprecated at - line 14.
'me@here.com'
'those@there.com'
'others@there.com'
'you@there.com'
'them@there.com'
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
Re^3: Splitting in while loop
by AnomalousMonk (Archbishop) on Oct 07, 2021 at 07:21 UTC
|
while (<DATA>)
{
...
}
assigns implicitly to $_ (see tybalt89's example)
(update: but see kcott's post
for a more complete discussion of $_ assignment
special-casing).
An arbitrary expression like split(...) does not. Had you had warnings enabled, Perl would have at least hinted at this problem.
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
Re^3: Splitting in while loop
by jwkrahn (Abbot) on Oct 07, 2021 at 07:21 UTC
|
while (split(/[, ]+/, <DATA>))
Is interpreted by perl as:
while ( @_ = split( /[, ]+/, <DATA> ) )
| [reply] [d/l] [select] |
|
Thanks jwkrahn, but if they're interpreted to be the same, then why does this code:
while (split(/[, ]+/, <DATA>))
{ print @_ }
print nothing, while this code:
#while (split(/[, ]+/, <DATA>)) # Edit: Sorry - ignore this
while (@_ = split(/[, ]+/, <DATA>)) # Edit: I meant this
{ print @_ }
prints:
me@here.com
those@there.comothers@there.com
you@there.comthem@there.com
?
Update: Cancel the above. I see AnomalousMonk's answer to it now. | [reply] [d/l] [select] |
|
$ perl -e '@_ = qw{a bcd ef}; print @_'
abcdef
If you put the array in interpolating quotes,
you will see each element separated by the value of the special variable $"
(which, by default, is a space):
$ perl -e '@_ = qw{a bcd ef}; print "@_"'
a bcd ef
$ perl -e '@_ = qw{a bcd ef}; print qq{@_}'
a bcd ef
In rare situations, perhaps where $" was changed elsewhere in the code,
you may want to make a localised change to $" (typically within an anonymous block).
See local,
"Temporary Values via local()" and
"Localization of special variables"
for more details on that.
Some examples:
$ perl -e '@_ = qw{a bcd ef}; { local $" = " "; print "@_" }'
a bcd ef
$ perl -e '@_ = qw{a bcd ef}; { local $" = "__"; print "@_" }'
a__bcd__ef
$ perl -e '@_ = qw{a bcd ef}; { local $" = "\n"; print "@_" }'
a
bcd
ef
| [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
|