2009-09-02 21 views
9

To jest pytanie dotyczące najlepszej praktyki.Kiedy operator statku kosmicznego jest używany poza sortowaniem?

Widziałem tylko operatora statku kosmicznego Perla (< =>) używanego w procedurach sortowania numerycznego. Ale wydaje się to przydatne w innych sytuacjach. Po prostu nie mogę myśleć o praktycznym użyciu.

Czy ktoś może podać przykład, kiedy może być używany poza sortowaniem Perla?

+0

@ether: tylko znacznik "operator"? Myślałem, że lubisz tworzyć nowe tagi operatora! –

Odpowiedz

7

Piszę system kontroli robota Joe, który chce iść do robota Mary i naładować ją. Poruszają się wzdłuż punktów całkowitych na linii. Joe zaczyna od $ j i może pokonać 1 metr w dowolnym kierunku na jednostkę czasu. Mary stoi nadal za $ m i nie może się ruszyć - potrzebuje dobrego doładowania! Program kontroli będzie wyglądać tak:

while ($m != $j) { 
    $j += ($m <=> $j); 
} 
2

W dowolnej metodzie porównywania. Na przykład możesz mieć skomplikowany obiekt, ale nadal ma zdefiniowaną "kolejność", więc możesz zdefiniować dla niego funkcję porównania (której nie musisz używać jako metody sortowania, ale nie jest to przydatne):

package Foo; 

# ... other stuff... 

# Note: this is a class function, not a method 
sub cmp 
{ 
    my $object1 = shift; 
    my $object2 = shift; 

    my $compare1 = sprintf("%04d%04d%04d", $object1->{field1}, $object1->{field2}, $object1->{field3}); 
    my $compare2 = sprintf("%04d%04d%04d", $object2->{field1}, $object2->{field2}, $object2->{field3}); 
    return $compare1 <=> $compare2; 
} 

Oczywiście jest to całkowicie wymyślny przykład. Jednak w kodzie źródłowym mojej firmy znalazłem prawie dokładnie powyższe, dla porównania obiektów używanych do przechowywania informacji o dacie i czasie.

Jeden inne wykorzystanie mogę pomyśleć, to do analizy statystycznej - jeśli wartość jest wielokrotnie uruchamiać na liście wartości, można stwierdzić, czy wartość jest wyższa lub niższa niż ustawiona w arytmetyczna mediana

use List::Util qw(sum); 
# $result will be 
# -1 if value is lower than the median of @setOfValues, 
# 1 if value is higher than the median of @setOfValues, 
# 0 if value is equal to the median 
my $result = sum(map { $value <=> $_ } @setOfValues); 

Oto jeszcze jeden, od wikipedia: "Jeśli nie można porównać dwóch argumentów (np. Jeden z nich to NaN), operator zwraca undef." tzn. możesz określić, czy dwie liczby są jednocześnie liczbami, ale osobiście wybrałbym mniej tajemniczy Scalar::Util :: szukany_numer.

+2

W rzeczywistości zachowanie 'undef' może powodować problemy, ponieważ' undef' w pewnym rodzaju spowoduje, że Perl najprawdopodobniej umrze. Ale możemy stworzyć sort numeryczny, który obsługuje NaN: 'sub numeric {$ a <=> $ b // ($ a == $ a) - ($ b == $ b)}' To posortuje NaN na początek, który ma pozytywny wpływ przynajmniej nie umierania. –

5

Operator <=> byłyby użyteczne dla binary search algorithm. Większość języków programowania nie ma operatora, który wykonuje trójdrożne porównanie, co powoduje konieczność wykonania dwóch porównań dla każdej iteracji. Dzięki <=> możesz zrobić tylko jedną.

sub binary_search { 
    my $value = shift; 
    my $array = shift; 
    my $low = 0; 
    my $high = $#$array; 

    while ($low <= $high) { 
     my $mid = $low + int(($high - $low)/2); 

     given ($array->[$mid] <=> $value) { 
      when (-1) { $low = $mid + 1 } 
      when (1) { $high = $mid - 1 } 
      when (0) { return $mid  } 
     } 
    } 

    return; 
} 
+0

Biorąc pod uwagę, jak zaskakująco trudno jest * poprawnie * wdrożyć wyszukiwanie binarne, mogę tylko mieć nadzieję, że nie przyczyniłem się do kolejnego zepsutego przykładu do świata. : P –

+0

Jaka jest korzyść z wydajności polegająca na delegowaniu tych dwóch porównań z wyraźnie napisanych oświadczeń do wewnętrznych elementów preprocesora? –

+1

Na poziomie bajtowym jest jeden operator, a nie dwa: 'perl -MO = Terse -e" $ a <=> $ b "' To powiedziawszy, ponieważ Perl jest zaimplementowany w C (który nie ma trójdrożnego operatora porównania) "<=>" musi być zaimplementowane jako dwa porównania przez elementy wewnętrzne. Wszelkie korzyści związane z wydajnością polegałyby na tym, że ekspansja odbywa się w C, a nie w Perlu. Oczywiście ostatecznym ograniczeniem jest to, co obsługuje zestaw instrukcji procesora, niezależnie od tego, co ma operator C. –