Perl, 갭이 있는 리스트에 대해 map과 foreach 내에서 $_ 조작할 때
자게에 언급된 코드골프때문에 평소에 잘 쓰지 않던 map 을 가지고 끙끙대고 있는데요. ( for(@a){} 보다는 map{}@a 가 더 짧으니까 ^^)
뜻하지 않은 에러가 자꾸 나서 왜 그런지 살펴보니 for와 map에서 좀 다르게 동작하는 부분이 있군요.
2 $array1[0] = 0; 3 $array1[9] = 9; # now $array1 = (0, undef, undef, ... , 9); 4 print "@array1", "\n"; # 0 "" "" ... "" 9 5 foreach (@array1) { 6 $_ *= 10 # $array1 = (0, 0, 0, ... , 90) 7 } 8 print "@array1", "\n"; # 0 0 0 ... 0 90
3번 라인에서 인덱스9 원소를 할당했으니, 인덱스1에서 8까지는 자동으로 생성되면서 값이 undef이 되는 걸로 알고 있는데, 이렇게 undef이 되는 시점이 정확히 언제인지 좀 묘해집니다.
어쨌거나, 4번 라인의 출력은 undef값이 널 스트링 취급되어서 0과 9만 나옵니다. (중간에 스페이스와 널스트링이 번갈아 나오니 몇 칸 떨어져서 나오겠죠.)
0 9
5-7번 라인에서 $_는 @array1의 각 원소의 alias가 되고, 10을 곱해주니 undef이던 게 0으로 취급되어서 결과적으로 0.
8번 라인에서 출력하면 이제는
0 0 0 0 0 0 0 0 0 90
이 되겠죠.
여기까지는 그러려니 하겠는데... map을 쓰면 다르더라고요.
11 $array2[0] = 0; 12 $array2[9] = 9; 13 print "@array2", "\n"; # 0 "" "" ... "" 9 14 map { $_ *= 10 } @array2; # ERROR 15 print "@array2", "\n";
이건 14번째 라인에서 에러 납니다.
Modification of a read-only value attempted at ./t2.pl line 14.
만일 13번 라인이 없을 때만 에러가 나고 있으면 에러가 안 난다면 오히려 수긍을 할 수도 있을 것 같은데, (일단 읽는 연산을 해야만 해당 인덱스가 생성된다는 식으로) 13번 라인에서는 잘 출력해놓고는 나중에 값을 바꾸려고 하면 에러가 나니 신기하군요.
애초에 map의 취지(?)가 배열의 값을 바꾸는 것보다는, 주어진 리스트를 가지고 새로운 리스트를 만들어내는 것이긴 합니다만, 위에서 보여주는 동작의 차이는 버그라고 봐야 되지 않을까 싶기도??
뉴스그룹에 올렸는데
아래 링크의 답변에 의하면 버그 맞대요. 제일 정확히 이유를 설명해주는 것 같네요. 버그라고 볼 지 feature라고 볼지는 논외로 치더라도...
http://groups.google.co.kr/group/comp.lang.perl.misc/tree/browse_frm/thread/2ae0ae0b6060cfcb/68cb746db33da09f?rnum=1&hl=ko&_done=%2Fgroup%2Fcomp.lang.perl.misc%2Fbrowse_frm%2Fthread%2F2ae0ae0b6060cfcb%2F68cb746db33da09f%3Ftvc%3D1%26hl%3Dko%26#doc_59de1e5bb1b11261
좋은 하루 되세요!
댓글 달기