[Moscow.pm] Узнать родительский ключ по ссылке
Alessandro Gorohovski
an.gorohovski на gmail.com
Пт Окт 4 06:45:48 PDT 2024
пт, 4 окт. 2024 г. в 16:20, Mons Anderson <mons на cpan.org>:
> On Fri, Oct 4, 2024 at 3:50 PM Alessandro Gorohovski via Moscow-pm <
> moscow-pm на pm.org> wrote:
>
>>
>>
>> пт, 4 окт. 2024 г. в 13:35, Mons Anderson <mons на cpan.org>:
>>
>>> On Fri, Oct 4, 2024 at 1:21 PM Alessandro Gorohovski via Moscow-pm <
>>> moscow-pm на pm.org> wrote:
>>>
>>>> По всей видимости, Denis имел ввиду
>>>> say
>>>> но это не имеет отношение к функции
>>>>
>>>> А всё остально будет работать на старых тоже.
>>>> :)
>>>>
>>>> Конечно, "положа руку на сердце", предложенная функция -- это вариация
>>>> через for
>>>> первоначального алгоритма через while, который предложил ув.
>>>> Steffen Winkler
>>>> sub where_key {
>>>> my $ref = shift;
>>>> while ( my ($key, $value) = each %h ) {
>>>>
>>>
>>> откуда тут возьмётся %h?
>>>
>>> $ref eq $value
>>>>
>>>
>>> это неверное сравнение.
>>> переменные могут быть равны по строковому значению, но быть разными
>>> переменными.
>>> \$ref == \$value более правильное.
>>>
>>
>> Да, конечно первоначальный вариант с while
>> не совсем корректно отработает на таком случае
>>
>> my %h = ( a => { b=> 1}, aa=> {bb=>2, ac=>2, ab=>2, }, );
>>
>> sub where_key {
>> my $hash = shift;
>> my $ref = shift;
>> while( my ($key, $value) = each %$hash ) {
>> $ref eq $value and return $key;
>> }
>> }
>>
>> say where_key( $h{aa}, $h{aa}{bb} );
>>
>> может выдать не только ожидаемый bb , а любой из
>> ab
>> ac
>> bb
>>
>> Вот поэтому и предложил другой вариант с for
>>
>> sub where_key {
>> my $hash = shift;
>> my $v;
>> for( %$hash ) {
>> return $v if \$_[ 0 ] eq \$_;
>> $v = $_;
>> }
>> }
>>
>>
>>
>>
>>>
>>>
>>>>
>>>> and return $key;
>>>> }
>>>> return;
>>>> }
>>>>
>>>
>>> А вообще имхо вся эта затея полный бред.
>>>
>>
>> Кому как.
>>
>>
>>
>>> Значение не несёт в себе информации о том, кто и откуда на него
>>> ссылается.
>>> Поэтому только по значению такой поиск не может считаться корректным.
>>> Только с передачей хэша в котором ищем это имеет смысл.
>>>
>>
>> Вообще здесь вопрос звучит более широко:
>>
>> Как зная ссылку на переменную (scalar, array or hash) найти её название?
>> Perl интерпретатор как то же находит, справляется с этим.
>>
>
> Perl никак не справляется с этим. Значение не имеет имени. Оно имеет >= 1
> ссылок на себя, каждая из которых равнозначно является её именем. Можно
> иметь на одну и ту же переменную ссылки из нескольких источников. И никакая
> из ссылок не является её "именем".
>
> Так что если поставить вопрос правильно, то задача начинает иметь смысл.
> Например:
> - как найти все ссылки на переменную?
>
> Я постарался подобрать решение исходя из поставленной задачи (по какой из
> ссылок переменную передали (скорее всего), если исходить из того, что она
> была передана из хэша.
> Поскольку мы обращались к хэшу прямо перед вызовом, это значит, что
> padwalker увидит переменную на один стекфрейм выше.
>
>
Да, ваше решение неплохо работает,
хотя не очень лаконичное и требует внешнего модуля
*use PadWalker ':all';*
действительно "видит" только на один уровень
и с такими случаями уже не справляется (не находит ничего)
my %h = ( a => { b=> 1}, aa=> {bb=>2, ac=>2, ab=>{ bb=>2, ac=>2, }, } );
detect( $h{aa}{ab} );
----------- следующая часть -----------
Вложение в формате HTML было извлечено…
URL: <http://mail.pm.org/pipermail/moscow-pm/attachments/20241004/9eb8e2bc/attachment.html>
Подробная информация о списке рассылки Moscow-pm