在Perl 5.20中,for循环似乎能够修改模块范围的变量,但不能在父范围内修改一个词法变量(并且不会引入新的范围,如果
#!/usr/bin/env perl
use strict;
use warnings;

our $x;

sub print_func {
    print "$x\n";
}

for $x (1 .. 10) {
    print_func; 
}

打印1到10像你所期望的,但以下不:

#!/usr/bin/env perl
use strict;
use warnings;

my $x;

sub print_func {
    print "$x\n";
}

for $x (1 .. 10) {
    print_func; 
}

发出以下警告10次:

Use of uninitialized value $x in concatenation (.) or string at perl-scoping.pl line 8.

这里发生了什么?我知道Perl子程序不能嵌套(并且始终具有模块范围),因此它们似乎无法关闭我的变量.看来,在这种情况下,严格模式下的perl应该使用以下消息拒绝第二个程序:

Global symbol "$x" requires explicit package name at perl-scoping.pl line 6.
Global symbol "$x" requires explicit package name at perl-scoping.pl line 9.

即它应该拒绝子例程,因为自由变量没有被声明为任何地方,而for循环因为变量尚未被声明.

为什么Perl以这种方式行事?

解决方法

令人困惑的是,记录在案的行为可能源自于使循环迭代器变量成为隐含的​​本地化全局而不是词汇的不良决定.从 Foreach Loops in perlsyn.

If the variable is preceded with the keyword my,then it is lexically scoped,and is therefore visible only within the loop. Otherwise,the variable is implicitly local to the loop and regains its former value upon exiting the loop. If the variable was prevIoUsly declared with my,it uses that variable instead of the global one,but it’s still localized to the loop.

换句话说,循环迭代器总是被定位到循环中.如果它是全局的,那么它的行为就像在循环块中被声明为本地的.如果它是一个词汇,那么它的行为就像它在循环块中被声明的那样.

将这个应用于您的两个示例将有助于了解发生了什么.

our $x;

sub print_func {
    print "$x\n";
}

for $x (1 .. 10) {
    print_func; 
}

在该循环中有一个隐式的本地$x. local真的应该被命名为temp.它在其范围内暂时覆盖全局变量的值,但它仍然是全局变量.这就是为什么print_func可以看到它.

当其范围结束时恢复旧值.如果在for循环之后添加print $x,可以看到这一点.

use v5.10;

our $x = 42;

for $x (1 .. 10) {
    say $x;
}

say $x;  # 42

我们来看看你的代码涉及到词汇(我的变量).

my $x;

sub print_func {
    print "$x\n";
}

for $x (1 .. 10) {
    print_func; 
}

这里真正发生的是你有两个词汇变量,称为$x.一个是文件范围,一个是范围的循环. for循环中的内部$x先于外部$x.这被称为“阴影”.

在物理范围之外不能看到词汇. print_func()只看到外部未初始化的$x.

这里有一些风格的外卖.

始终将参数传递到您的函数中.

实际上,print_func应该有一个参数.那么你不用担心复杂的范围规则.

sub print_func {
    my $arg = shift;
    print "$arg\n";
}

for $x (1..10) {
    print_func($x);
}

总是用于我的$x.

不要依赖于复杂的隐式for循环范围规则.总是用我的声明循环迭代器.

for my $x (1..10) {
    print_func($x);
}

避免全局变量

由于很难说出访问全球的内容,不要使用它们.如果你认为你需要一个全局的,写一个函数来控制对一个文件范围的词法的访问.

my $Thing = 42;
sub get_thing { return $Thing }
sub set_thing { $Thing = shift; return }

声明您的变量接近他们使用的位置.

Ye olde编码风格将做一些事情,例如将所有变量声明在文件或函数的顶部.这是一个非常非常非常古老的语言,它要求只在某些地方声明变量. Perl和大多数现代语言没有这样的限制.

如果您一次性声明您的变量,就很难知道它们的内容,很难知道使用或影响的变量.如果你声明它接近于它的第一次使用,限制什么可以影响它,并使它更明显它是什么.

perl-for循环不会修改`my`变量,但是修改`我们的’变量的更多相关文章

  1. ios – 如何从变量访问属性或方法?

    是否可以使用变量作为Swift中方法或属性的名称来访问方法或属性?在PHP中,您可以使用$object->{$variable}.例如编辑:这是我正在使用的实际代码:解决方法你可以做到,但不能使用“纯粹的”Swift.Swift的重点是防止这种危险的动态属性访问.你必须使用Cocoa的Key-ValueCoding功能:非常方便,它完全穿过你要穿过的字符串到属性名称的桥,但要注意:这里是龙.

  2. iOS >>块>>更改块外部的变量值

    我不是在处理一个Object并改变它,就像我的mString一样.我希望’center’属性的行为类似于myInt,因为它是直接访问的C结构,而不是指向对象的指针.我希望’backgroundColor’的行为类似于我的imstring,因为它是一个指向一个新对象的对象的指针,不是吗?

  3. ios – Xcode Bot:如何在post触发器脚本上获得.ipa路径?

    我正在使用机器人来存档iOS应用程序,我需要获取.ipa产品路径才能将其发布到我们的分发系统中.机器人设置:并使用脚本打印所有env变量,其中不包含ipa文件的路径.此外,一些变量指向不存在的目录,即:XCS_OUTPUT_DIR这里的env变量输出:除此之外,我还能够确认.ipa文件是在另一个文件夹中创建的(/IntegrationAssets//

  4. ios – 使用附加字符串本地化Info.plist变量

    我正在尝试本地化应用程序的名称,同时仍然能够根据构建配置追加字符串.所以目前它被设置为:该设置定义为:通过这种方式,我们可以为应用程序添加后缀以用于不同的beta版本.问题是,当我们尝试本地化本地化的InfoPlist.strings中的应用程序显示名称时,就像这样我们覆盖存储在Info.plist中的值,并丢失后缀字符.这有什么好办法吗?

  5. iOS – 开始iOS教程 – 变量之前的下划线?

    这是正确的还是我做错了什么?

  6. ios – 静态计算变量被多次实例化

    我有一个日期格式化程序,我试图在UITableViewCell子类中创建一个单例,所以我创建了一个这样的计算属性:问题是我不止一次看到print语句,这意味着它不止一次被创建.我已经找到了其他方法,但我很想知道这里发生了什么.有任何想法吗?解决方法您的代码段相当于只获取属性,基本上它与以下内容相同:如果你只想运行一次,你应该像定义一个惰性属性一样定义它:

  7. ios – UIApplication.delegate必须仅在主线程中使用[复制]

    我应该在主调度中的viewControllers中声明这些)变量位置声明定义了它的范围.您需要确定这些变量的范围.您可以将它们声明为项目或应用程序级别(全局),类级别或特定此功能级别.如果要在其他ViewControllers中使用这些变量,则使用公共/开放/内部访问控制将其声明为全局或类级别.

  8. ios – 无法理解Objective-C块文档

    为什么localVariable“按价值使用?”>如果我在第二个例子中将__block存储类型添加到localVariable,我错误地假设该块关闭了变量,所以它将它保留在堆中直到块被释放?解决方法Howexactlyisoneexample“accessedbyreference”whiletheotheroneisaccessedbyvariable?self是当前正在执行找到块的方法的对象.强引用只是意味着对象的保留计数增加.IfIaddthe__blockstoragetypetolocalVar

  9. ios – 为BOOL变量编写getter和setter

    显然,使用obj-c,通常没有理由编写getter和setter(感谢有用的mr@synthesize).所以现在,需要做到这一点,我遇到了一个我不知道如何编写它们的问题.:p我敢肯定我可能不会以正确的方式解决我的问题–只是将我的对象子类化得更容易–但我正在尝试编写类别代码以添加属性,因为(在开头)它更快,因为我想学习如何在我的应用程序中使用类别代码.我有这个:我在setter中没有if查询就试过

  10. ios – 为什么不保留__block变量(在非ARC环境中)?

    我正在阅读__blockvariables上的文档,并考虑我使用__block的情况.对我来说,似乎我需要两种情况:>在块中使用时将变量标记为读写>在块内引用self时避免保留周期从表面上看,这两件事似乎并不相关.我认为__block变量没有被保留为更多的技巧我需要记住避免保留周期的特定用例.我想知道,为什么不能保留它们是否有更重要的建筑理由?

随机推荐

  1. 数组 – Perl中有什么神奇的数组?

    在Perldocumentationforreverse中,我发现:“请注意,将数组反转到自身(如@a=reverse@a)将尽可能保留不存在的元素;即对于非魔法数组或具有EXISTS和DELETE方法的绑定数组.什么属性区分神奇和非魔法阵列?解决方法一个神奇的阵列是一个执行它的操作不仅仅是改变内容.只有内置的魔术阵列是@ISA,而且这是非常不明显的.正如句子所暗示的,魔术阵列主要是一个绑定的阵列

  2. perl – 使用“isa”方法的最佳方式?

    什么是“最好的”使用方式“isa()”可靠?解决方法Scalar::Util实现明确更好.它避免了eval{}的开销,它总是导致设置一个附加变量.Scalar::Util实现更容易阅读.如果eval也失败了,我相信发生的是你在树之前向后走到eval之前的状态–这是如何实现复位状态.这带来了额外的故障开销.基准根本不是一个对象对象传递isa检查对象出现故障现象检查测试代码:我使用这是为i486-linux-gnu-thread-multi建立的perl,v5.10.1(*),以及Scalar::Util,1

  3. 在CORE :: GLOBAL中哪些Perl内置函数不能被覆盖?

    解决方法toke.c中任何值为负的值都可以被覆盖;所有其他人可能不会.你可以看源码here.例如,我们来看看第10,396行的waitpid:由于waitpid为负数,因此可能会被覆盖.grep怎么样?这是积极的,所以不能被覆盖.这意味着以下关键字不能被覆盖:chop,defined,delete,do,dump,each,else,elsif,eval,exists,for,foreach,format,glob,goto,grep,if,keys,last,local,m,map,my,next,no

  4. 如何在Perl中打印由换行符分隔的列表元素?

    什么是最简单的打印所有列表的元素以Perl中的换行符分隔的元素?解决方法在Perl5.10中:其他方式:或:或者怎么样?

  5. 使用Perl如何获取文件大小(以兆字节为单位)?

    我想以磁盘的形式获取磁盘上的文件大小.使用-s运算符给出了以字节为单位的大小,但是我将假设,然后将其除以魔术数字是一个坏主意:我应该使用只读变量来定义1024,还是有一种编程方式来获取一千字节的字节数?

  6. perl – 如何测试/分类CPAN模块的utf8正确性

    例如:File::Slurp,如果你将读取该文件您将根据命令行开关获得不同的结果,并且perl-CSDA将无法正常工作.伤心.(是的,我知道比Encode::decode(“utf8”,read_file($file,binmode=>’:raw’));将帮助,但是SAD.我的问题:>在这里任何首选方式,如何测试/分类什么CPAN模块是utf8安全/准备/正确?>这里是像Perl::Criticforutf8这样的东西–什么将检查模块源可能的utf8不正确?总结以上是DEVMAX为你收集整理的perl–如

  7. 如何删除Perl字符串中的空格?

    如果我声明一个值为’3’的变量$myString.是否有任何功能来删除返回值的空格.有点像SomeFun然后返回’3′.输出:你可以注意到’vid’=>‘0’,上面的代码从theanswer.我正在研究它.总结以上是DEVMAX为你收集整理的如何删除Perl字符串中的空格?如果觉得DEVMAX网站内容还不错,欢迎将DEVMAX网站推荐给好友。

  8. 如何在mod_perl2下运行Devel :: Cover?

    Unfortunately,Devel::Coverdoesnotyetworkwiththreads.它也不适用于prefork.在startup.pl中使用,Devel::Cover问题perl5.8.9,Apache2.2.13.我的操作系统是FreeBSD,如果重要.同样的问题是reportedforwin32.更新:PerlTrace全部输出解决方法邪恶之源似乎是Apache::DBI.

  9. 如何使用Perl中的C类?

    我有一套用C写的课.从Perl脚本中调用它们的最佳方法是什么?

  10. perl – 在Emacs中以双模式更好的缩进

    我正在使用Emacs来修改Perl和Verilog交织的代码.我正在使用two-mode-mode在两者之间切换,这样可以预期.问题是perl代码与//一行一行地表示;如下图所示:而双模式则认识到它是Perl,它是逐行的,所以缩进等在线上无意义.我想做的是使Perl代码像往常一样格式化,但忽略//;字符.有什么想法吗?我刚刚开始偷看模式文件,它们是可以理解的复杂的,所以任何提示都不会感激!

返回
顶部