كيف يمكنني إنشاء اسم متغير بيرل بناءً على سلسلة؟

StackOverflow https://stackoverflow.com/questions/2275463

  •  21-09-2019
  •  | 
  •  

سؤال

في بيرل ، هل من الممكن إنشاء متغير عالمي يعتمد على سلسلة؟

على سبيل المثال ، إذا كان لدي وظيفة مثل:

sub create_glob_var {
    my ($glob_var_str) = @_;
    # something like this ( but not a hash access).
    our ${$glob_var_str};
};

وأدعتها مثل:

create_glob_var( "bar" );

كيف يمكنني التعديل create_glob_var لإنشاء متغير عالمي يسمى بالفعل $bar?

مشروعي يستخدم Perl 5.8.5.

تعديل

ما يلي لا يعمل:

use strict;
BEGIN {
  sub create_glob_var {
    my ($glob_var_str) = @_;
    no strict 'refs';
    $$glob_var_str = undef;  # or whatever you want to set it to
  }

  create_glob_var("bah");
};

$bah = "blah";

ينتج عنه:

Variable "$bah" is not imported at /nfs/pdx/home/rbroger1/tmp2.pl line 12.
Global symbol "$bah" requires explicit package name at /nfs/pdx/home/rbroger1/tmp2.pl line 12.
Execution of /nfs/pdx/home/rbroger1/tmp2.pl aborted due to compilation errors.

ملاحظة أدرك أن استخدام أسباب المتغيرات العالمية استنزاف الأوزون وصلع النمط الذكور. أحاول تنظيف بعض التعليمات البرمجية القديمة المصابة بالفعل باستخدام المتغيرات العالمية. Refactor في وقت واحد ...

هل كانت مفيدة؟

المحلول

إذا كنت تحاول تنظيف الكود القديم ، فيمكنك كتابة وحدة نمطية تصدر المتغير (المتغيرات) المطلوبة. في كل مرة تشعر فيها بالحاجة إلى الاحتجاج create_glob_var, ، بدلاً من ذلك ، أضف متغيرًا إلى هذه الحزمة ووضعها في قائمة الاستيراد.

سيساعدك ذلك على تتبع ما يجري وكيف يتم استخدام المتغيرات.

package MyVars;

use strict; use warnings;

use Exporter 'import';

our($x, %y, @z);

our @EXPORT_OK = qw( $x %y @z );

النص:

#!/usr/bin/perl

use strict;use warnings;

use MyVars qw( $x %y @z );

$x = 'test';
%y = (a => 1, b => 2);
@z = qw( a b c);

use Data::Dumper;
print Dumper \($x, %y, @z);

انتاج:

$VAR1 = \'test';
$VAR2 = {
          'a' => 1,
          'b' => 2
        };
$VAR3 = [
          'a',
          'b',
          'c'
        ];

نصائح أخرى

sub create_glob_var {
    my ($glob_var_str) = @_;
    no strict 'refs';
    $$glob_var_str = undef;  # or whatever you want to set it to
}

ال no strict 'refs' ضروري فقط إذا use strict في الواقع ، وهو ما ينبغي أن يكون دائما.

إضافة:

إذا كنت تسأل عما إذا كانت هناك طريقة لكتابة روتين فرعي create_glob_var بحيث ينجح الرمز التالي:

use strict;
create_glob_var("bar");
$bar = "whatever";

... ثم الجواب هو "رقم" ومع ذلك ، بيرل vars سيفعل براغما ما تريد:

use strict;
use vars qw($bar);
$bar = "whatever";

ولكن هذا نوع من ترميز بيرل على الطراز القديم. في الوقت الحاضر ، عادة ما يفعل ذلك:

use strict;
our $bar = "blah";

our يمكن أيضًا إعلان المتغيرات العالمية التي يمكن استخدامها بحرية لاحقًا:

our ($foo, @bar, %baz);
# ...
$foo = 5;
@bar = (1, 2, 3);
%baz = (this => 'that');

حاول النظر في هذا السؤال:هل لدى Perl متغيرات ديناميكية تشبه PHP؟

باختصار ، يبدو أنك يجب أن تكون قادرًا على القيام به $$glob_var_str = "whatever";

سيكون عليك استخدام eval, ، ولكن هذا يعتبر بشكل عام الشر. شيء مثل:

eval("$glob_var_str = \@_;");

تعديل

فقط تحقق من أنه يمكنك فقط القيام بذلك بدون my ومع no strict refs.

ال vars تقوم Pragma بالفعل بالرفع الثقيل لما تريد ، لذا ضعه في العمل:

#! /usr/bin/perl

use warnings;
use strict;
use vars;

BEGIN { vars->import(qw/ $bah /) }

$bah = "blah";
print $bah, "\n";

إذا كنت تفضل تهجئته create_glob_var, ، ثم استخدام

#! /usr/bin/perl

use warnings;
use strict;
use vars;

sub create_glob_var { vars->import("\$$_[0]") }

BEGIN { create_glob_var "bah" }

$bah = "blah";
print $bah, "\n";

في كلتا الحالتين ، الإخراج هو

blah

أشعر بالفضول لمعرفة سبب رغبتك في القيام بذلك بهذه الطريقة بدلاً من إعلان هذه المتغيرات our. نعم ، قد يتطلب الأمر بعض التكرارات للقبض عليها جميعًا ، لكن هذه إصلاحات قصيرة الأجل على أي حال ، أليس كذلك؟

بشكل عام ، يمكنك استخدام متغير كاسم متغير (انظر "المراجع الرمزية" في Perlref) ، لكنك حقًا ، حقًا ، هل حقا لا تريد أن تفعل ذلك: تمكين strict 'refs' براغما تعطيل هذه الميزة.

أظهر رافائيل جارسيا-سواريز حكمة عظيمة عندما كتب ، "لا أعرف ما هي مشكلتك الأصلية ، لكنني أقترح استخدام تجزئة".

أنظر أيضا:

الجواب من قبل سنان ünür هو في الواقع الأفضل. ومع ذلك ، فقد اختر هذا فضولي ، لذلك فعلت القليل من القراءة (Perldoc perlmod) وتعلمت عن "package_name ::" هاش كوسيلة للوصول إلى مساحة اسم الحزمة.

يضيف الرمز التالي سجلًا إلى جدول الرمز الرئيسي :: الحزمة:

use strict;
my $name = "blah";
my $var = "sss";
$main::{$name} = \$var;

print "$main::blah\n";

هذا يطبع "SSS".

ومع ذلك ، اضطررت إلى إضافة اسم الحزمة لطباعة البيان لأن "استخدام صارمة" لا يزال ينخدع. سأستمر في البحث - لا يبدو أن استخدام VARS يعمل في الوقت الحالي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top