Какой оператор наиболее эффективен для сравнения любых двух элементов? - PullRequest
4 голосов
/ 04 апреля 2020

Часто мне нужно преобразовать данные из одного типа в другой, а затем сравнить их. Некоторые операторы сначала преобразуют в указанные типы c, и это преобразование может привести к потере эффективности. Например, у меня может быть

my $a, $b = 0, "foo"; # initial value
$a = (3,4,5).Set;     # re-assign value
$b = open "dataFile"; # re-assign value

if $a eq $b { say "okay"; } # convert to string
if $a == 5 { say "yes"; }   # convert to number
if $a == $b {} # error, Cannot resolve caller Numeric(IO::Handle:D: );

Операторы «eq» и ​​«==» сначала преобразуют данные в удобоваримые типы и могут замедлить работу. Будут ли операторы «eqv» и «===» пропускать конвертирующие типы данных и будут более эффективными, если сравниваемые данные не будут известны заранее (т. Е. Вы абсолютно не знаете, что собираетесь получить заранее)?

Ответы [ 2 ]

9 голосов
/ 04 апреля 2020

Мне не совсем понятно из вопроса, действительно ли вы хотите , чтобы преобразования произошли или нет.

Операторы типа == и eq действительно являются вызовами multi sub s с именами типа infix:<==>, и есть много кандидатов. Например, есть один для (Int, Int), который выбирается, если мы сравниваем два Int s. В этом случае он знает, что ему не нужно приводить, и просто выполнит целочисленное сравнение.

Операторы eqv и === не приведут; первое, что они делают, это проверяют, что значения имеют один и тот же тип, и если они этого не делают, они go не более. Убедитесь, что вы используете правильный вариант в зависимости от того, хотите ли вы использовать семантику снимка (eqv) или ссылочную семантику (===). Обратите внимание, что типы действительно должны быть точными одинаковыми, поэтому 1e0 === 1 не получится истинным, поскольку одно значение равно Num, а другое - Int.

. Поведение с автоматическим приведением таких операторов, как == и eq, может быть очень удобным, но с точки зрения производительности это также может быть ловушкой. Они принуждают, используют результат принуждения для сравнения, а затем выбрасывают его. Повторные сравнения могут, таким образом, многократно вызывать принуждения. Если у вас есть такая ситуация, имеет смысл разделить работу на две фазы: сначала «проанализировать» входящие данные на соответствующие типы данных, а затем go и выполнить сравнение.

Наконец, в При любом обсуждении эффективности стоит отметить, что оптимизатор времени выполнения хорош в удалении повторяющихся проверок типов. Таким образом, хотя в принципе, если вы читаете встроенный источник, == может показаться более дешевым в случае, если две вещи имеют одинаковый тип, потому что не требуется, чтобы они были точно одного типа, в действительности эта дополнительная проверка все равно будет оптимизирована для ===.

6 голосов
/ 04 апреля 2020

Обе === и eqv сначала проверяют, относятся ли операнды к одному и тому же типу, и возвращают False, если это не так. Поэтому на этом этапе между ними нет реальной разницы.

Оператор a === b действительно короток для a.WHICH eq b.WHICH. Таким образом, он вызовет метод .WHICH для операндов, который может быть дорогостоящим, если операнд является чем-то вроде действительно большого Buf.

Оператор a eqv b более сложен в том смысле, что он имеет специальный регистр много сравнений объектов, поэтому в целом вы не можете много говорить об этом.

Другими словами: YMMV. И если вы действительно заинтересованы в производительности, бенчмарк! И будьте готовы адаптировать свой код, если другой способ решения проблемы окажется более производительным.

...