Programing

왜“!!”

lottogame 2020. 12. 11. 07:42
반응형

왜“!!” Perl에서 잘못된 형식으로 간주됩니까?


최근의 면접 과정에서 소위 "비밀" !! 연산자 를 사용하는 샘플 Perl 코드를 제출했습니다 . 나중에 코드에 대해 논의 할 때 면접관 중 한 명이 내가 왜 그것을 사용하기로 선택했는지 물었고 그것이 잘못된 형식으로 간주되었다고 말했습니다. 그는 이유에 대해 자세히 설명하지 않았습니다.

저희 팀과 저는이 연산자가 "나쁜 형태"로 간주된다는 사실을 깨닫지 못한 채 수년간이 연산자를 사용해 왔습니다.

"뱅뱅"연산자에 부작용이나 기타 예기치 않은 동작이 있습니까? 어떤 사람들은 왜 그것을 "나쁜 형태"로 간주합니까? 관용적 대안이 있습니까?

다음은 내가 !!허용 및 / 또는 바람직 하다고 생각할 있는 몇 가지 예 입니다.

  1. 부울 추가의 예인 코딩 실습의 실제 코드 :

    while (my $line = <$F>) {
        # snip
        exists $counts{lines} and $counts{lines} += !! chomp $line;
    }
    
  2. 부울 값을 해시 키로 사용 (명확하게 간단한 예) :

    sub foo {
        my ($input) = @_;
        my %responses = ( '' => "False", 1 => "True" );
        return $responses{ !! $input };
    }
    
  3. 비트 연산에서 부울을 사용하거나 심지어 pack():

    sub foo {
        my ( $a, $b, $c ) = @_;
        my $result = !!$a + (!! $b)<<1 + (!! $c)<<2;
        return $result;
    }
    
  4. 특정 값만 진실이라고 간주하는 데이터베이스와 같은 외부 라이브러리 / 프로세스에서 사용할 유형 변환을 수행해야합니다.

    my $sth = $dbh->prepare("INSERT INTO table (flag,value) VALUES (?,?)")
    $sth->execute("i_haz_cheeseburger", !! $cheeseburger_string)
    

귀하는 !!펄이 모호한 것들의 활용 : 특정 값이 !반환하고, 가능한 값 중 하나가 dualvar이라고 (문자열과 숫자를 모두 포함하는 스칼라). !!이러한 행동을 복합화하는 데 사용 하는 것은 당연합니다. 그 섬세함은 큰 장점이 될 수 있지만 오히려 큰 마이너스가 될 수도 있습니다. "이 프로젝트에서는 Perl 사용이 금지되어 있습니다."라는 프로젝트를 요구하는 기능을 사용하지 마십시오.

$count += !! (some_expression)그 표현의 진실 값의 발생을 계산 하는 많은 대안이 있습니다 . 하나는 삼항 $count += (some_expression) ? 1 : 0입니다. 그것도 약간 모호합니다. 원하는 작업을 수행하는 멋진 간단한 방법이 있습니다. post-if를 사용하는 것입니다.

$x++ if some_expression;

이것은 당신이하는 일을 정확히 말해줍니다.


단순히 필요하지 않기 때문에 '나쁜 형태'라고 부릅니다. Perl에서 부울 변환을 수행 할 필요가 없습니다. 그래서 기껏해야 중복되고 최악의 경우 난독 화입니다.

Perl에서 사용할 수있는 정말 멋진 트릭이 있지만 언어의 가장 큰 문제 중 하나는 (적어도 지각 적으로) 코드가 "한 번만 작성"하는 경향이 있다는 것입니다.

결국 스칼라를 테스트 할 수 있는데 왜 부울을 얻기 위해 스칼라를 '이중 부정'해야합니까?

my $state = !! 'some_string';
if ( $state ) { print "It was true\n" };

또는:

if ( 'some_string' ) { print "It was true\n" };

그리고 그것은 사실입니다. "비밀"연산자, 구두점 기반 변수 등으로 인해 끔찍하게 이해할 수없는 Perl 코드를 작성할 수 있습니다. 그리고 잘 작동합니다. 예를 들어-저는 여전히 이것을 걸작이라고 생각합니다. 3D 스테레오 그램, 자기 복제 출처

그러나 그것은 '좋은 코드'가 아닙니다. '실제'사용을 위해서는 코드가 명확하고 이해하기 쉬우 며 문제 해결이 쉬워야합니다.

대안에 관하여

while (my $line = <$F>) {
    # snip
    exists $counts{lines} and $counts{lines} += !! chomp $line;
}

이것은 ... 얼마나 자주 당신이 chomp내가 생각하는 대사를 성공적으로 편집 했는지 계산하는 것입니까? 따라서 기본적으로 입력의 줄 수를 계산합니다.

이를 위해 '사용 $.'을 생각할 것 입니다. 내가 당신의 코드에 대해 심오한 것을 놓친 것이 아니라면?

"이거 씹지 않으면 어떡하지?"

글쎄요. 어때 :

 $counts{lines}++ if foo();

이를 위해 :

sub foo {
    my ($input) = @_;
    my %responses = ( "" => "False", 1 => "True" );
    return $responses{ !! $input };
}

나는 그것을 다음과 같이 쓸 것입니다.

sub foo {
    my ($input) = @_;
    return $input ? "True" : "False";
}

For the last condition - packing flags into a byte:

sub flags {
    my @boolean_flags = @_;
    my $flags = 0;
    for ( @boolean_flags ) {
        $flags<<=1;
        $flags++ if $_;
    }
    return $flags;
}

print flags ( 1, 1, 1 );

Or perhaps if you are doing something like that - taking a leaf from how Fcntl does it by defining values to add based on position, so you're not having to worry about the positional arguments problem:

You can request that the flock() constants (LOCK_SH, LOCK_EX, LOCK_NB and LOCK_UN) be provided by using the tag :flock.

And then you can:

flock ( $fh, LOCK_EX | LOCK_NB );

They're defined bitwise, so they 'add' via the or operator - but that means it's an idempotent operation, where setting LOCK_NB twice wouldn't be.

For example,

 LOCK_UN = 8
 LOCK_NB = 4
 LOCK_EX = 2
 LOCK_SH = 1

If we expand the question to the less subjective:

I'm asking for the reasons to avoid !!

  • Perl evaluates "truth" of variables, so there's not really much need for an actual logical boolean.
  • Conditional statements are clearer than their equivalent boolean algebra. if ( $somecondition ) { $result++ } is clearer than $result += !! $somecondition.
  • It's on a secret operator list because it's obscure. Your future maintenance programmers may not appreciate that.
  • !!1 is 1, !!0 is dualvar('', 0). While that's quite flexible, it can surprise, especially since most people don't even know what a dualvar is, much less that ! returns one. If you use a ternary, it's explicit what values you get:$value ? 1 : 0

The whole question is somewhat subjective, so I'd like to give an opinion that differs from the other answers posted so far. I wouldn't consider double negation bad form in general, but I'd try to avoid it if there's a more readable alternative. Regarding your examples:

  1. Use something like $count++ if $condition.

  2. Truth values as hash keys? That's simply evil. At least, it's surprising for anyone who has to maintain your code.

  3. Here the use of !! is justified.

  4. Here I'd use the ternary operator. It isn't really clear how execute behaves when passed a dualvar.

Another situation where it's completely OK to use !! is when casting certain values to Boolean, for example in a return statement. Something like:

# Returns true or false.
sub has_item {
    my $self = shift;
    return !!$self->{blessed_ref};
}

Most programmers should know the !! idiom from statically typed languages where it's often used as a cast to bool. If that's what you want to do and there's no danger of unwanted side-effects, go with the double negation.


Perhaps it's not so bad for code only you see.

However, your fellow developer might see it one day fixing a bug in your code, and stumbles upon this. There are two options

  1. He thinks you made a mistake and removes one !, invalidating your code
  2. He thinks this is just software rot, and removes both !! without a second thought. After refactoring some other code, it suddenly hangs on... a type mismatch?

Either way, it will waste the time of future developers, unless they happen to be familiar with it. Intelligible code is never for yourself (well, it could help), but for any others who will ever see your code.


Depending on the job, it's bad form for a lot of business and interview reasons as well...

  1. when working on a team project, or any other code where many other developers could be working on it, don't obfuscate (or follow company policy)
  2. going of what sanchises said, it will cause more work, and does not clearly display the intentions of the code.
  3. it's simply unnecessary, and as discussed above - it sounds like there is at least one scenario where the result would not work - hence a bug.
  4. showing uses of obscure coding in an interview, when there is an easier and clearer way to do it doesn't look favorably in an interview.
  5. an interview is the place where you want to show that you are a team player, not that you are going to whip out weird crap that nobody else understands (unless it happens to be the answer to an unsolved issue of course)

p.s. it would have been in good form to ask the interviewer why he considered it "bad form". A handy interview followup tip, would be to send him a thank you and ask him why he considers it "bad form"

참고URL : https://stackoverflow.com/questions/33014080/why-is-considered-bad-form-in-perl

반응형