2014-05-01 20 views
14

Tôi đã nhận ra (một cách khó khăn) rằng toán tử eq cho một lỗi thời gian chết khi một toán hạng là một đối tượng với quá trình chuỗi hóa quá tải.Tại sao `eq` không hoạt động khi một đối số đã quá tải chuỗi?

Dưới đây là một ví dụ nhỏ:

my $test = MyTest->new('test'); 
print 'yes' if $test eq 'test'; 

package MyTest; 

use overload '""' => sub { my $self = shift; return $self->{'str'} }; 

sub new { 
    my ($class, $str) = @_; 
    return bless { str => $str }, $class; 
} 

Kết quả của hoạt động này là:

Operation "eq": no method found, 
    left argument in overloaded package MyTest, 
    right argument has no overloaded magic at ./test.pl line 7. 

Kỳ vọng của tôi từ việc đọc perlop sẽ là chuỗi bối cảnh buộc trên cả hai toán hạng, bắn các stringification phương pháp trong $test, sau đó các chuỗi kết quả được so sánh. Tại sao nó không hoạt động? Điều gì thực sự hapenning?

Ngữ cảnh trong đó tôi gặp sự cố này là trong tập lệnh sử dụng cả số autodieTry::Tiny. Trong khối try, tôi die với một số thông điệp cụ thể bị bắt. Nhưng trong khối catch, khi tôi kiểm tra xem liệu $_ eq "my specific message\n", điều này có thời gian chạy không nếu $_ là một autodie::exception.

Tôi biết tôi sẽ phải thay thế $_ eq "..." bằng !ref && $_ eq "...", nhưng tôi muốn biết lý do.

+1

thử '" $ test "eq 'test'' –

+0

@HunterMcMillen, đã hoạt động, cảm ơn. Nhưng tôi không thấy điều gì khác biệt với người phiên dịch! – scozy

+2

'eq' so sánh không thực sự buộc' $ test' được xâu chuỗi, nó chỉ sử dụng chuỗi so sánh trên các đối số của nó. –

Trả lời

20

Bạn chỉ quá tải chuỗi, không so sánh chuỗi. tuy nhiên overload pragma sẽ sử dụng stringification quá tải cho việc so sánh chuỗi nếu bạn chỉ định fallback => 1 tham số:

my $test = MyTest->new('test'); 
print 'yes' if $test eq 'test'; 

package MyTest; 

use overload 
    fallback => 1, 
    '""' => sub { my $self = shift; return $self->{'str'} }; 

sub new { 
    my ($class, $str) = @_; 
    return bless { str => $str }, $class; 
} 

Chi tiết về lý do tại sao công trình này:

Khi trao một đối tượng quá tải, các nhà điều hành eq sẽ cố gắng để gọi quá tải eq. Chúng tôi không cung cấp quá tải và chúng tôi đã không cung cấp quá tải cmp mà từ đó eq có thể được tự động phát. Do đó, Perl sẽ phát hành lỗi đó.

Với fallback => 1 enabled, lỗi bị chặn và Perl sẽ làm những gì nó sẽ làm anyway - ép buộc đối số thành chuỗi (yêu cầu quá tải chuỗi hoặc phép thuật khác) và so sánh chúng.

Các vấn đề liên quan