2014-08-31 2 views
0

이 예제에서는 적응 형 서브 루틴을 코딩하는 가장 좋은 방법을 배우고 싶습니다.적응 형 트림 서브 루틴

텍스트를 자르는 서브 루틴이 필요합니다 (실제로는 구실이며 내 서브 루틴은 다른 작업을 수행했을 수 있습니다).

더 다재다능하기 위해, 나는 인자의 다른 유형을 받아 내 서브 루틴을 싶습니다

my @input = (' A ', ' B', 'C ');

  1. my @trimmed = trim(@input);

  2. trim(\@input);

  3. my $out = trim($input[0]);는 반환 'A'

  4. trim(\$input[0]); @input의 첫 번째 요소를 자른다.

  5. trim(\@a, \@b, \@c); 문자열의 각 어레이 트리밍

  6. my $out = trim(\@a, ' A ', ' B'); $ 아웃 = (QW/A B /); 나는 위의 제안 입력의 다른 종류의 지원이 구현의 더 나은 솔루션

    sub trim { 
        state $re = qr/^\s+|\s+$/m; 
        my @a; 
        for(@_) { 
         if(ref eq 'SCALAR') { $$_ =~ s/$re//g; } 
         elsif(ref)   { trim(\$_) for(@$_); } 
         else    { push @a, s/$re//gr; } 
        } 
        return \@a if @a > 1; 
        return $a[0] if $a[0]; 
    }  
    

    있습니까 :

여기에 내 현재 추한 솔루션입니다 (동작 논의 할)?

이 질문의 주된 이유는 문자열, 문자열 배열 또는 해시에 저장할 수있는 텍스트를 가지고있는 최종 응용 프로그램에 관한 것입니다.

나는 그것을 작성하는 것이 좋습니다 가정 :

trim(\@allmytexts); 
align(\@allmytexts, align=>'right'); 

보다 :

for(@allmytexts) { 
    trim($_); 
    align($_, align=>'right'); 
} 

답변

1

이 질문은 주제 꺼져 있고 가능성이 곧 종료됩니다.

그러나 "이러한 유형의 동작을 이러한 서브 루틴에서 요청하는 것이 맞습니까?"

아니요. 나는이 서브 루틴이 내 앞에있는 정보로 무엇을하고 싶은지에 관해서는 분명치 않다. 문서를 언급하지 않고 나는 그것을 사용하지 않았다면 그것을 부르는 법을 기억하기 위해 분명히 어려움을 겪을 것이다. 하루 이틀. 모든 사람이 글을 쓰면서 쓰는 것을 볼 수 있습니다.

$string = trim($string) 

그들이 기억하기 때문에.

그것은 또한 당신이 때문에 일부 호출이 무엇

my $out = trim(\@a, ' A ', ' B'); $out = (qw/A B/); (behavior to be discussed) 

난 당신이 다른 전달 메커니즘 언어에 사용되는 것으로 의심,이 같은 것이 유용 할 것이다 자신을 취소하지 않을 것 같습니다. Perl에서 은 모두이고 별칭은입니다. 따라서 @_ 배열의 요소에 대한 연산은 실제 매개 변수에 대한 동일한 연산과 동일합니다. 즉, 해당 값을 매개 변수로 전달하면 서브 루틴이 쓰기 가능한 값을 수정할 수 있습니다. 이 자리에서 수정되어야 함을 나타 내기 위해 참조을 통과 염두에두고

는 함께 참조 할 가지고있는 방해물로, 서브 루틴 행동하는 방법을 지시 플래그에 지나지 않는다 사용하기 전에 역 참조.

자주 사용하는 라이브러리 기능이 얼마나 자주이 기능을 사용하는지 보았는지 직접 자문 해보십시오. 예를 들어, 과 rindex을 매우 비슷한 것으로 처리하고 기존 코어 연산자 lctrim이 수행하려고 시도하는 것과 비슷하지만 합리적으로 하나의 매개 변수를 사용하고 변환 된 결과를 반환합니다. sprintfprintf의 변종으로 볼 수 있습니다. 으로 알고 있는데, 파일 핸들 매개 변수가 스칼라에 대한 참조 인 경우 문자열을 파일 핸들에 쓰지 않고 변수에 넣어야합니다. 그러나 그것은 그렇게 설계되지 않았습니다.

나는 정의 된 문제에 대한 대안 솔루션만을 제공 할 수 있습니다. 실생활의 어려움을 설명하지 않고, 당신이 당신의 trim이 무엇을해야하는지 확신 할 수 없기 때문에 누군가가 당신을 도울 수 있다면 의심 스럽습니다.

다른 질문은 참조가 전달되고 그 값이 제자리에서 수정 될 때 반환 값은 무엇이되어야 하는가입니다. 변경된 후에 값을 돌려 주어야한다는 것이 명백 할 수도 있지만, 적응 코드를 작성하기 때문에 호출이 스칼라,리스트 또는 void 문맥인지 여부에 따라 리턴 값을 변경하는 방법은 무엇입니까? 또는, 더 나은, 당신이 나에게 너무 복잡한 소리

my $n = q{    999      }; 
++trim($n); 
+0

나는 동의한다. 하나 또는 두 개의 호출 스타일 지원 -'trim (\ $ inplace)'및/또는'$ output = trim ($ input)'을 제안합니다. 호출자가 전체 배열을 다듬을 필요가 있다면 Perl은 그들이 사용할 수있는 완벽하게 좋은'map'과'for' 키워드를 가지고 있습니다. – tobyink

+0

@tobyink : 암시하려했기 때문에 참조를 지나가는 기능을 나타내는 플래그로 전달하는 것에 동의하지 않습니다. 'trim ($ string, inplace => 1)'또는'trim_inplace ($ string)'과 같은 것이 괜찮습니다. – Borodin

+0

@borodin, 왜 제 질문이 주제와 관련이 없다고 생각합니까? – nowox

2

같은 것을 쓸 수 trimlvalue subroutine 있도록합니다. 사용법은 그것보다 읽기 쉽고 기억해야합니다! [1]. trim에 스칼라 값을 지정하십시오 (기본값은 $_).

sub trim(_) { $_[0] =~ s/^\s+|\s+\z//rg } 

모든 귀하의 경우는 쉽게 당신은 너무에서 적절한 버전을 만들 수 있습니다

$x = trim($x); 
@a = map trim, @a; 

로 시작, 그 처리 할 수 ​​있습니다.

sub trim_i(_) { s/^\s+|\s+\z//g for $_[0] } 

다음과 같이 사용합니다 :

trim_i($x); 
trim_i for @a; 

다른 가능성은 스칼라의 목록 (기본값 없음) 걸릴 것입니다.

sub trim_i { 
    s/^\s+|\s+\z//rg for @_; 
} 

trim_i($x); 
trim_i(@a); 

sub trim { 
    wantarray 
     ? map s/^\s+|\s+\z//rg, @_ 
     : $_[0] =~ s/^\s+|\s+\z//rg 
} 

$x = trim($x); 
@a = trim(@a); 

그러나 그것은 조금 이상한. 특히 my $x = trim($y, $z);부터 가능합니다.


  1. 또한, 펄 좋은 생각이 아니다 유형 기반의 다형성을 사용합니다. 문자열이 과부하 된 객체에 직면하면 코드가 예기치 않게 작동합니다.