note
jcb
<p>Other monks have explained where the <c>undef</c> values are coming from, but have not explained why your program still works despite the warnings. Since you were honest about this being a homework assignment, I will take some time to explain.</p>
<p>Your program works anyway because neither of the elements in <c>@drop</c> are <c>undef</c>, and while <c>undef eq undef</c> (with two warnings) in Perl, <c>undef ne $string</c> if <c>$string</c> is a <del>defined</del> <ins>true</ins> value.</p>
<p>Here is the contents of the <c>@colors</c> array on each iteration of the loop, both before and after an element is possibly removed. The element that <c>$num</c> refers to is <u>underlined</u>.</p>
<pre>
0: before: <u>red</u> green blue yellow pink purple brown
0: after: <u>red</u> green blue yellow pink purple brown
--
1: before: red <u>green</u> blue yellow pink purple brown
1: after: red <u>green</u> blue yellow pink purple brown
--
2: before: red green <u>blue</u> yellow pink purple brown
2: after: red green <u>blue</u> yellow pink purple brown
--
3: before: red green blue <u>yellow</u> pink purple brown
3: after: red green blue <u>yellow</u> pink purple brown
--
4: before: red green blue yellow <u>pink</u> purple brown
4: after: red green blue yellow <u>purple</u> brown
--
5: before: red green blue yellow purple <u>brown</u>
5: after: red green blue yellow purple
--
6: before: red green blue yellow purple
6: after: red green blue yellow purple
--
</pre>
<p>I modified the code slightly to print that. While I cannot show you exactly what I used without giving away an answer that you should find, this code shows what the "before" and "after" parts mean:</p>
<code>
my @colors = qw(red green blue yellow pink purple brown);
my $count = @colors;
my @drop = qw(pink brown);
my $num = 0;
foreach $num (1..$count){
$num--;
print $num, ": before: @colors\n";
if ($colors[$num] eq $drop[0] or $colors[$num] eq $drop[1]){
splice (@colors, $num, 1);
}
print $num, ": after: @colors\n--\n";
}
print "@colors \n";
</code>
<p>This technique of inserting additional output to show a program's intermediate states is commonly known as "printf debugging", after the common output function in the C programming language. Perl also has [doc://printf], but [doc://print] is far more commonly used.</p>
<p>The bug in your code that [haukex] mentioned should be easy to see now, and I will give a few hints towards the "two lines of code" that [haukex] mentioned:</p>
<ol>
<li>How do you construct a hash from a list in Perl?</li>
<li>How can you use [doc://map] to construct such a list?</li>
<li>How do you test for the existence of a hash key?</li>
<li>What does [doc://grep] do in Perl?</li>
</ol>
<p>And another issue:</p>
<ol>
<li value="5">How can you avoid the wasted seventh iteration of the loop? <small>(Hint: What are the loop control operators in Perl?)</small></li>
</ol>
<p>Good luck on your adventures in learning Perl.</p>
<p><small><i>Edited 2019-08-18 by [jcb]: Fix logical error pointed out by [haukex]: <c>undef</c> is <b>not</b> special under <c>eq</c> and stringifies to an empty string.</i></small></p>
11104608
11104608