2012-03-20 2 views
4

Net::SSL является частью Crypt :: SSLeay. Во время работы над докладом об ошибке сегодня меня отвлекало то, как много раз появлялся бедный старый *.Почему код в Net :: SSL разыменовывает typeglobs, где я не вижу необходимости?

Для примера рассмотрим Net::SSL::configure:

*$self->{ssl_version} = $ssl_version; 
*$self->{ssl_debug} = $ssl_debug; 
*$self->{ssl_arg} = $arg; 
*$self->{ssl_peer_addr} = $arg->{PeerAddr}; 
*$self->{ssl_peer_port} = $arg->{PeerPort}; 

Может быть, это потому, что я не знаком с предустановленным 5.8 Perl, но я просто не могу точно определить, есть ли существенная причина для использования * на LHS. Не хватит ли только *$self->{ssl_peer_port} = $arg->{PeerPort};? Или, здесь что-то глубокое (например, local $_ против local *_)?

ответ

2

У меня нет установленного модуля, поэтому проверить его достаточно легко, но я полагаю, что это потому, что объект является globref; то есть ссылка на блаженный типglob.

Здесь нет псевдонимов. Когда вы пишете

*$self->{ssl_debug} = $ssl_debug; 

Сначала он переводит globref обратно в полный тип glob. Затем он захватывает только хэш-аспект типаglob и переходит к разыменованию этого.

Это не пре-или пост-5.8 вещь.

Как вы думали, что это было?

+0

Я смутился и думал, что '$ self -> {ssl_debug}' обрабатывается как typeglob. Спасибо за ответ. Причина, по которой я привел до 5.6, состоит в том, что я не знаю, чего я не знаю ;-) –

+1

@ SinanÜnür Подумайте об этом как о приоритете, в котором префикс-диференцы идут первыми перед постфиксными. Или думать о '->' как о том, как '$ {...}' вокруг его левой стороны. Когда в C вы читаете '* argv [0]', это действительно '* (argv [0])', но в Perl, '$$ aref [0]' is '$ {$ aref} [0]' not '$ {$ AREF [0]} '. Другие префиксные разделители, включая '*', также идут первыми. Таким образом, ваше выражение было '$ {* $ self} {ssl_debug}' - что, возможно, могло ухудшить ситуацию, если вы случайно столкнулись с этим в дикой природе. :) – tchrist

1

tchrist (как всегда) на правильном пути. Вы можете поиграть с IO::Socket и посмотреть, что вы можете и не можете сделать со ссылками на блаженные типы.

use IO::Socket; 
$foo = IO::Socket->new; 

print $foo;      # IO::Socket=GLOB(0x20467b18) 
print *$foo;      # *Symbol::GEN0 
print ref($foo);     # IO::Socket 
print ref(*$foo);    # "" 

*$foo->{key} = value;   # ok 
$$foo->{key} = value;   # ok 
$foo->{key} = value;    # Not a HASH reference at ...