Programing

Perl에서 "0 but true"는 무엇을 의미합니까?

lottogame 2020. 11. 29. 09:31
반응형

Perl에서 "0 but true"는 무엇을 의미합니까?


누군가 Perl에서 문자열 "0 but true"가 정확히 무엇을 의미하는지 설명 할 수 있습니까? 내가 아는 한, 정수 비교에서는 0과 같지만 부울로 사용하면 true로 평가됩니다. 이 올바른지? 이것은 언어의 정상적인 동작입니까, 아니면 인터프리터에서 특수한 경우로 취급되는 특수 문자열입니까?


언어의 정상적인 행동입니다. perlsyn맨 페이지 인용 :

숫자 0, 문자열 '0'"", 빈 목록 ()undef부울 컨텍스트에서 모두 거짓입니다. 다른 모든 값은 참입니다. true 값을 부정 !하거나 not특별한 false 값을 반환합니다. 문자열로 평가되면로 처리 ""되지만 숫자로 처리되면로 처리됩니다 0.

이 때문에 (성공적인) 반환 값으로 0반환 될 것으로 예상되는 시스템 호출에서 반환 0하고 실제로 거짓 값을 반환하여 실패 사례를 알릴 수있는 방법이 있어야합니다. "0 but true"그 목적을 달성합니다.


Perl 코어에 하드 코딩되어 숫자로 취급되기 때문입니다. 이것은 Perl의 규칙과 ioctl규칙이 함께 작동하도록 만드는 해킹입니다 . 에서 perldoc -f ioctl:

ioctl(및 fcntl) 의 반환 값은 다음과 같습니다.

if OS returns:      then Perl returns:

    -1              undefined value
     0              string "0 but true"
anything else       that number

따라서 Perl은 성공하면 true를 반환하고 실패하면 false를 반환하지만 운영 체제에서 반환하는 실제 값을 쉽게 확인할 수 있습니다.

$retval = ioctl(...) || -1;
printf "System returned %d\n", $retval;

특수 문자열 "0 but true"-w부적절한 숫자 변환에 대한 불만 에서 면제됩니다 .


다른 사람들이 말한 것 외에도 "0 but true"숫자 컨텍스트에서 경고하지 않는다는 점에서 특수한 경우 입니다.

$ perl -wle 'print "0 but true" + 3'
3
$ perl -wle 'print "0 but crazy" + 3'
Argument "0 but crazy" isn't numeric in addition (+) at -e line 1.
3

0 but true은 Perl에서 특별한 경우입니다. 당신의 단순한 인간의 눈에는 숫자처럼 보이지 않지만 현명하고 현명한 Perl을 아는 모든 사람들은 그것이 실제로 숫자라는 것을 이해합니다.

이는 Perl 서브 루틴이 0 값을 리턴 할 때 루틴이 실패했거나 거짓 값을 리턴했다고 가정한다는 사실과 관련이 있습니다.

두 숫자의 합을 반환하는 서브 루틴이 있다고 상상해보십시오.

die "You can only add two numbers\n" if (not add(3, -2));
die "You can only add two numbers\n" if (not add("cow", "dog"));
die "You can only add two numbers\n" if (not add(3, -3));

첫 번째 명령문은 서브 루틴이 1. 잘 됐네요. 두 번째 문은 서브 루틴이 cowdog 에 추가 할 수 없기 때문에 죽습니다 .

그리고 세 번째 진술?

음,에 추가 3수 있습니다 -3. 나는 단지을 얻었 0지만 add서브 루틴이 작동 하더라도 내 프로그램이 죽을 것입니다 !

이 문제를 해결하기 위해 Perl 0 but true은 숫자로 간주 합니다. add 서브 루틴이 0 이 아니라 0이 아니라 true를 반환 하면 세 번째 명령문이 작동합니다.

그러나 0이지만 사실 은 숫자 0입니까? 다음을 시도하십시오.

my $value = "0 but true";
print qq(Add 1,000,000 to it: ) . (1_000_000 + $value) . "\n";
print "Multiply it by 1,000,000: " . 1_000_000 * $value . "\n";

네, 제로입니다!

인덱스 서브 루틴은 펄의 아주 오래 된 조각과 개념 전에 존재 0하지만 사실은 주변에 있었다. 문자열에있는 하위 문자열의 위치를 ​​반환한다고 가정합니다.

index("barfoo", "foo");   #This returns 3
index("barfoo", "bar");   #This returns 0
index("barfoo", "fu");    #This returns ...uh...

마지막 문장은 -1. 즉, 이렇게하면 :

if ($position = index($string, $substring)) {
   print "It worked!\n";
}
else {
   print "If failed!\n";
}

일반적으로 표준 기능으로 수행하는 것처럼 작동하지 않습니다. 두 번째 문에서와 같이 "barfoo"와 "bar"를 else사용하면 절이 실행되지만 세 번째 문에서와 같이 "barfoo"와 "fu"를 사용하면 if절이 실행됩니다. 내가 원하는 것이 아닙니다.

그러나 index서브 루틴이 0을 리턴 했지만 두 번째 명령문과 undef세 번째 명령문에 대해 참이면 my if/ else절이 작동했을 것입니다.


또한 Perl 코드에서 사용 된 문자열 "0E0"을 볼 수 있으며 이는 동일한 의미입니다. 여기서 0E0은 지수 표기법으로 작성된 0을 의미합니다. 그러나 Perl은 "0", ''또는 undef 만 false로 간주하므로 부울 컨텍스트에서 true로 평가됩니다.


Perl의 소스 코드, 특히 numeric.c의 Perl_grok_number_flags에 하드 코딩되어 있습니다.

그 코드를 읽으면서 "infinity"(대소 문자 구분 안 함) 문자열이 looks_like_number 테스트도 통과한다는 것을 발견했습니다. 나는 그것을 몰랐다.


정수 컨텍스트에서는 0 (문자열 시작 부분의 숫자 부분)으로 평가되고 0입니다. 스칼라 컨텍스트에서는 비어 있지 않은 값이므로 참입니다.

  • if (int("0 but true")) { print "zero"; }

    (출력 없음)

  • if ("0 but true") { print "true"; }

    (참으로 인쇄)


0 은 Perl (및 C와 관련된 다른 언어)에서 거짓을 의미합니다. 대부분의 경우 이는 합리적인 행동입니다. 다른 언어 (예 : Lua)는 0 을 true로 취급 하고 true 가 아닌 값을 나타내는 또 다른 토큰 (종종 nil 또는 false )을 제공합니다.

Perl 방식이 잘 작동하지 않는 한 가지 경우는 숫자를 반환하거나 어떤 이유로 함수가 실패하면 거짓 값을 반환하려는 경우입니다. 예를 들어, 파일에서 한 줄을 읽고 줄의 문자 수를 반환하는 함수를 작성하는 경우입니다. 함수의 일반적인 사용법은 다음과 같습니다.

while($c = characters_in_line($file)){
    ...
};

특정 행의 문자 수가 0이면 while 루프는 파일의 끝 전에 종료됩니다. 따라서 characters_in_line 함수는 특수한 경우 0 문자를 사용해야하며 대신 '0 but true'반환해야 합니다. 이렇게하면 함수가 while 루프 에서 의도 한대로 작동 하지만 숫자로 사용되는 경우 정답도 반환합니다.

이것은 언어의 일부가 아닙니다. 오히려 문자열을 숫자로 해석하는 Perl의 기능을 이용합니다. 그래서 때때로 다른 찌르기가 대신 사용됩니다. 예를 들어 DBI"0E0" 을 사용합니다. 숫자 컨텍스트에서 평가되면 0 을 반환 하지만 부울 컨텍스트에서는 false 를 반환 합니다.


잘못된 것 :

  • "".
  • "0".
  • 그것들을 엄격하게하는 것들.

"0 but true" 그 중 하나가 아니므로 거짓이 아닙니다.

또한 Perl은 "0 but true"0을 반환했지만 함수가 성공했음을 알리기 위해 숫자가 예상되는 위치를 반환합니다. sysseek 는 이러한 함수의 예입니다. 값이 숫자로 사용될 것으로 예상되므로 Perl은이를 숫자로 간주하도록 코딩됩니다. 결과적으로 숫자로 사용될 때 경고가 발생하지 않고 looks_like_number("0 but true")true를 반환합니다.

다른 "참 제로"는 http://www.perlmonks.org/?node_id=464548 에서 찾을 수 있습니다 .


"0 but true"의 또 다른 예 :

The DBI module uses "0E0" as a return value for UPDATE or DELETE queries that didn't affect any records. It evaluates to true in a boolean context (indicating that the query was executed properly) and to 0 in a numeric context indicating that no records were changed by the query.


I just found proof that the string "0 but true" is actially built into the interpreter, like some people here already answered:

$ strings /usr/lib/perl5/5.10.0/linux/CORE/libperl.so | grep -i true
Perl_sv_true
%-p did not return a true value
0 but true
0 but true

When you want to write a function that returns either an integer value, or false or undef (i.e. for the error case) then you have to watch out for the value zero. Returning it is false and shouldn't indicate the error condition, so returning "0 but true" makes the function return value true while still passing back the value zero when math is done on it.


"0 but true" is a string just like any other but because of perl's syntax it can serve a useful purpose, namely returning integer zero from a function without the result being "false"(in perl's eyes).

And the string need not be "0 but true". "0 but false" is still "true"in the boolean sense.

consider:

if(x)

for x:        yields:
1             -> true
0             -> false
-1            -> true
"true"        -> true
"false"       -> true
"0 but true"  -> true
int("0 but true") ->false

The upshot of all of this is you can have:

sub find_x()

and have this code be able to print "0" as its output:

if($x = find_x)
{
   print int($x) . "\n";
}

The string ``0 but true'' is still a special case:

for arg in "'0 but true'" "1.0*('0 but true')" \
           "1.0*('0 but false')" 0 1 "''" "0.0" \
           "'false'" "'Ja'" "'Nein'" "'Oui'" \
           "'Non'" "'Yes'" "'No'" ;do
    printf "%-32s: %s\n" "$arg" "$(
        perl -we '
            my $ans=eval $ARGV[0];
            $ans=~s/^(Non?|Nein)$//;
            if ($ans) {
                printf "true:  |%s|\n",$ans
            } else {
                printf "false: |%s|", $ans
          };' "$arg"
        )"
    done

give the following: (note the ``warning''!)

'0 but true'                    : true:  |0 but true|
1.0*('0 but true')              : false: |0|
Argument "0 but false" isn't numeric in multiplication (*) at (eval 1) line 1.
1.0*('0 but false')             : false: |0|
0                               : false: |0|
1                               : true:  |1|
''                              : false: ||
0.0                             : false: |0|
'false'                         : true:  |false|
'Ja'                            : true:  |Ja|
'Nein'                          : false: ||
'Oui'                           : true:  |Oui|
'Non'                           : false: ||
'Yes'                           : true:  |Yes|
'No'                            : false: ||

... and don't forget to RTFM!

man -P'less +"/0 but [a-z]*"' perlfunc

       ... "fcntl".  Like "ioctl", it maps a 0 return from the system call
           into "0 but true" in Perl.  This string is true in boolean
           context and 0 in numeric context.  It is also exempt from the
           normal -w warnings on improper numeric conversions. ...

참고URL : https://stackoverflow.com/questions/129945/what-does-0-but-true-mean-in-perl

반응형