Подтвердить что ты не робот

Как сравнить ссылки на Perl?

Я хочу проверить, указывает ли две ссылки на один и тот же объект. Кажется, я могу просто использовать

if ($ref1 == $ref2) { 
 # cheap numeric compare of references
 print "refs 1 and 2 refer to the same thing\n";
}

как упоминалось в perlref, но я смутно помню, как можно использовать какую-либо функцию для той же цели. Есть ли какая-то причина, по которой я не должен использовать простой тест с числовым равенством?

Примечание. Я хочу знать только, ссылаются ли ссылки на один и тот же объект. Я не ищу способ сравнить содержимое объекта (ов).

4b9b3361

Ответ 1

Ссылки, по умолчанию, указывают на их адреса. Эти ссылочные адреса уникальны для каждой ссылки, поэтому ее часто можно использовать при проверке равенства.

Однако в приведенном фрагменте вы должны сначала убедиться, что оба $ref1 и $ref2 являются фактически ссылками. В противном случае вы можете получить неправильные результаты из-за регулярных скаляров, содержащих ссылочные адреса.

Кроме того, ничто не гарантирует ссылки на нумерацию на их адрес. Например, объекты могут использовать перегрузку, чтобы влиять на возвращаемое ими значение в разных контекстах.

Более твердым способом, чем сравнение ссылок непосредственно для числового равенства, будет использование функции refaddr, предоставляемой Scalar::Util, после убедившись, что обе стороны на самом деле являются ссылками.

Ответ 2

Функция, которую вы ищете, это refaddr из Scalar::Util (после проверки того, что сравниваемые значения действительно являются ссылками):

use Scalar::Util 'refaddr';

if ($obj1 and ref($obj1) and $obj2 and ref($obj2) and
    refaddr($obj1) == refaddr($obj2))
{
    # objects are the same...
}

Ответ 3

Я должен предположить, что ваш #comment о том, как дешево (= быстро) тест равенства был там по какой-то причине. Учитывая это, вы, вероятно, должны продолжать использовать дегустационный тест равенства. Это очень быстро, намного быстрее, чем eq, не говоря уже о сравнении любого типа.

Возможно, что объект с прямо или косвенно перегруженным оператором == может узурпировать тест для своих целей. Но если это так, вы можете даже предпочесть его опосредованный ответ.

Какой подход вы используете, может зависеть от того, что вы знаете об объектных классах. Подходы, которые применяются к общим случаям, не всегда оптимальны для конкретных. Чем больше вы знаете о чем-то, тем больше вы можете его оптимизировать - и наоборот.

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

До тех пор, пока вы понимаете проблемы перегрузки, ошибочно считать один подход правильным, а другой - неправильным. У каждого есть своя цель. Если бы всегда было неправильно делать то, что вы делаете, тогда эта операция была бы запрещена или, по крайней мере, предупреждалась.

Вы заметите, что это не так заметно.