[첫화면으로]Perl/변수

마지막으로 [b]

1. perl 의 변수
2. 특수한 스칼라 변수
3. Scope
3.1. global (package) variable
3.2. lexical variable
3.3. runtime scope
3.4. 스코프에 영향을 미치는 것
4. Global 변수 보충
5. 수와 문자열
5.1. 수로 다룰 때와 문자열로 다룰 때의 차이로 인한 오작동 사례
6. 기타 & Comments

1. perl 의 변수

2. 특수한 스칼라 변수

3. Scope

3.1. global (package) variable

$main::name   = "Your Name Here";
$Fred::name   = "Fred Flintstone";
$Barney::name = "Barney Rubble";

print "\$name in package main   is $name\n";         # 현재 패키지의 $name, 이 경우 $main::name
print "\$name in package Fred   is $Fred::name\n";
print "\$name in package Barney is $Barney::name\n";

$main::name   = "Your Name Here";
$Fred::name   = "Fred Flintstone";
$Barney::name = "Barney Rubble";

print "\$name in package main   is $name\n";
package Fred;
print "\$name in package Fred   is $name\n";
package Barney;
print "\$name in package Barney is $name\n";
package main;

3.2. lexical variable

my $var; 로 선언

3.3. runtime scope

local $var; - 해당 블록이 끝날때까지는 서브루틴으로 점프해도 영향을 미친다. lexical 변수는 그렇지 않음
my $x = 10;              # Line 5
$_ = "alpha";
{
   my $x = 20;         # 이것은 이 블록 안에서만
   local $_ = "beta";  # 이것은 somesub()에까지 영향을 미친다
   somesub();          # Line 10
}
somesub();

sub somesub {
   print "\$x is $x\n";
   print "\$_ is $_\n";
}

$x is 10
$_ is beta
$x is 10
$_ is alpha

$/와 같은 특수 변수를 다루는 경우를 제외하면, local을 쓰는 것을 지양하고 my를 쓸 것. 전역 변수를 조작해야 하는 경우가 생긴다면 디자인을 새로 하는 것을 고려해보라고 함2

3.4. 스코프에 영향을 미치는 것

요점:

4. Global 변수 보충

요점:

5. 수와 문자열

5.1. 수로 다룰 때와 문자열로 다룰 때의 차이로 인한 오작동 사례

어떤 스칼라 변수의 초기값이 숫자였을 때, 이것을 문자열 결합 연산자 .를 쓰거나 따옴표 안에 넣어 interpolate시키거나 할 경우 그 시점에 문자열 값이 추가되는 걸 알 수 있다.

use Devel::Peek;

my $inc = 5;
Dump($inc);
print '<',$inc,'>', "\n";
Dump($inc);
print '<'.$inc.'>', "\n";   # 이 시점. 또는 "[$inc]"도 마찬가지
Dump($inc);

SV = IV(0x7fa88382d728) at 0x7fa88382d738
  REFCNT = 1
  FLAGS = (PADMY,IOK,pIOK)
  IV = 5
<5>
SV = IV(0x7fa88382d728) at 0x7fa88382d738
  REFCNT = 1
  FLAGS = (PADMY,IOK,pIOK)
  IV = 5
<5>
SV = PVIV(0x7fa88382f820) at 0x7fa88382d738
  REFCNT = 1
  FLAGS = (PADMY,IOK,POK,pIOK,pPOK)
  IV = 5
  PV = 0x7fa88340bd70 "5"\0
  CUR = 1
  LEN = 16

그리고 Cpan:Search::Elasticsearch 의 메쏘드 중에, 간단한 자바(정확히는 자바 기반인 MVEL) 코드를 바로 넣어서 elasticsearch 엔진에 전달할 수 있는데,
    $es->update(
        ...
        body => {
            script => "ctx._source.num += inc",  # 따옴표 안에 MVEL 코드
            params => { inc => $inc }, # 여기!!!
        }
    );

$inc가 수 값만 있을 때는 JSON으로 변환된 내용이 "params" : { "inc" : 5 }인데, PV값도 있을 경우는 "params" : { "inc" : "5" }로 전달되고, 이게 위의 += inc에 적용되면 수의 덧셈이 아니라 문자열 합치기가 되어버린다. 기존의 num 필드의 값이 3이었다면 8이 되어야 할 것이 "35"가 되어버리는 불상사가 생김.

앞에서 봤듯이 스칼라 변수에 PV값이 생기는 시점이 문자열처럼 다루기 시작할 때라서, 처음 만들었던 코드는 아무 문제가 없었는데, 비슷하게 만든 다른 코드는 계속 문제가 생기고, 알고보니 테스트를 위해 미리 변수값을 print 시키면서 "[$inc]" 이런 식으로 스트링으로 다룬 게 원인이었다. Perl 스칼라 변수의 특성과 특정 모듈의 동작과 자바의 + 연산자 오버로딩이 만나서 아주 기묘한 결과를 낳음.

해결책은 params => { inc => 0+$inc }와 같이, $inc 변수의 값을 다시 온전한 숫자로 변환하는 것.

6. 기타 & Comments

이름:  
Homepage:
내용:
 

컴퓨터분류
각주:
1. Perldoc:Perlmod
2. Beginning Perl, 1st ed. 260p

마지막 편집일: 2014-4-10 9:52 am (변경사항 [d])
9087 hits | Permalink | 변경내역 보기 [h] | 페이지 소스 보기