The reason this happens is because the while loop is designed to operate on <> like an iterator. Thus, it reads one line at a time until it can't read anymore.

By contrast, using <> as the list for your map block reads the entire file in all at once, incrementing $. along the way. The entire file then gets passed to your map block as one big list, and by this time, $. has already been incremented to the number of the last line, so the same $. gets printed each time through the map block.

is special. it does not act like any other iteration construct, not even like any other while() construct. It explicitly iterates over each record ("line") one by one instead of converting the whole file to a list first.