передача ha sh подпрограмме (ам) - PullRequest
2 голосов
/ 02 марта 2020

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

В любом случае, часть, которая заставила меня задуматься о том, что должен быть лучший способ, - это строки:

%mdc_def = mysub(\%mdc);
%mdc = %$mdc_def;

... глупо для меня, но я не нахожу способ сделать эти две строки просто одной ... что-то вроде (даже если это плохой синтаксис):

%mdc = %mysub(\%mdc);

Тогда, если бы у меня был mysub2, который также должен был бы иметь, что sh Я должен был бы сделать то же самое двухстрочное перемешивание в этой подпрограмме также. Это просто грязно.

Вот фрагмент, над которым я работаю:

use strict;
use warnings;

my %mdc = ();
my $mdc_def;

$mdc{abc} = 123;
$mdc{cde} = 234;

foreach (sort keys (%mdc)) { print "before $_ = $mdc{$_}\n"; }
$mdc_def = mysub(\%mdc);
%mdc = %$mdc_def;
foreach (sort keys (%mdc)) { print " after $_ = $mdc{$_}\n"; }

sub mysub {
  my ($mdc_def) = @_;
  my %m = %$mdc_def;

  $m{def} = 345;
  $m{efg} = 456; 

  return \%m;
}

Заранее спасибо.

Ответы [ 3 ]

5 голосов
/ 02 марта 2020

Вы можете использовать следующее:

sub mysub {
   my ($mdc_def) = @_;
   my %m = %$mdc_def;

   $m{def} = 345;
   $m{efg} = 456; 

   return \%m;
}

my %mdc = ( a=>1, b=>2 );

%mdc = %{ mysub(\%mdc) };

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

sub mysub {
   my ($mdc_def) = @_;
   my %m = %$mdc_def;

   $m{def} = 345;
   $m{efg} = 456; 

   return \%m;
}

my $mdc = { a=>1, b=>2 };

$mdc = mysub(\%mdc);

Это оставляет один экземпляр копирования. Этот экземпляр необходим, если вы не хотите, чтобы mysub изменил ha sh на месте, поэтому приведенный выше код подходит.

Следующая версия, которая изменяет ha sh, - место, избегая второго экземпляра копирования (и позволяя нам оставить глобальную переменную как ha sh).

sub mysub_inplace {
   my ($mdc_def) = @_;
   $mdc_def->{def} = 345;
   $mdc_def->{efg} = 456; 
}

my %mdc = ( a=>1, b=>2 );

mysub_inplace(\%mdc);
1 голос
/ 02 марта 2020

Попробуйте

%mdc = %{mysub(\%mdc)};
  • \%mdc передаст ссылку на %mdc га sh в качестве параметра на mysub suroutine
  • % {mysub (…)} будет обрабатывать возвращаемое значение mysub call как ссылку ha sh и преобразовывать его в ha sh

Вы можете использовать прототип подпрограммы sub mysub (\%) для вызова mysub с mysub(%mdc)


Простой рабочий пример / скрипт:

#!/usr/bin/perl
# Original version constained prototypes for sub mysub - 
# see ikegami comments below the answear
use strict;
use warnings;

sub mysub {
  my( $hRef ) = (@_);
  $hRef->{a} = 0;
  $hRef->{c} = 3;
  return $hRef;
}

my %mdc = ( a=>1, b=>2);

%mdc = %{mysub(\%mdc)};
print %mdc;
0 голосов
/ 02 марта 2020

У вас есть понимание, что такое $hash_ref = \%hash и как его использовать?

use strict;
use warnings;
use feature 'say';

my %mdc = ();

$mdc{abc} = 123;
$mdc{cde} = 234;

say '- Before ------------';

while( my($k,$v) = each %mdc ) {
    say "$k => $v";
}

mysub(\%mdc);

say '- After -------------';

while( my($k,$v) = each %mdc ) {
    say "$k => $v";
}

sub mysub {
  my $mdc_ref = shift;

  $mdc_ref->{def} = 345;
  $mdc_ref->{efg} = 456; 
}

Вывод

- Before ------------
cde => 234
abc => 123
- After -------------
def => 345
cde => 234
abc => 123
efg => 456
...