Это будет работать.
my %h = %{shift @_};
Это не будет.
my %h = ${$_[0]} # not ${$_[0]}
Этот символ должен быть %
my %h = %{$_[0]}
также use warnings;
и use strict;
СОВЕТ: Причина, по которой вышеприведенный пример не работает, только в одном примере не объявляется лексическая переменная %h = %{$href};
не my %h = %{$href};