b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

Perl 符号表和 typeglob

电脑杂谈  发布时间:2019-07-23 02:09:36  来源:网络整理

perl数组函数_perl scalar函数_perl fork函数

* * 整数类型表 字符数据类型表 实数类型表 字符串类型 程序界面(设计时) 运行结果 关系运算符表 逻辑运算符表 逻辑运算的真值表 集合运算规则表 位运算符 位运算示例 object pascal各运算符的优先级 声明语句应该按照标号、常量、类型、变量、过程和函数的顺序来声明。从上面的示例代码中可以看出,无论是非严格模式还是严格模式下,当处在对象下面方法的第一个this为指向该对象,第一个console.log(this,this==obj),打应出来当然是该obj对象,由词法作用域分析可得,该this的上下文为multiply属性,而multiply又是挂载在obj对象下面的,显然this指向该obj对象,而至于为什么第二个返回的结果是nan,this所指向window,multiply的匿名函数内嵌套一submultiply函数,当在执行调用submultiply()函数时,它其实是暴露在整个全局作用域下的,注意在非严格模式下,submultiply函数内的this是指向widow全局对象的,既然this是全局window的,你相当于在全局作用域下添加了一个window.num1,window.num2属性,但是并没有赋初始值啊,一个非数值运算当然返回nan了,注意这里的num1,num2不是挂载在obj下的,而是window下的,注意两者的区别,也许你会以为会同名变量不是可以覆盖么,若我在submultiply()函数内声明一个变量,不就可以了么,如果不带var 声明num1,num2变量并且赋值,那么是可以的,但是若是使用了var 的话依然是nan,因为在函数内声明变量为局部变量,这里的this始终是指向window的,不要被作用域链给迷糊的了的,这两者是有区别的,而在严格模式下,submultiply()函数内的this谁也不指向,返回一个undefined,如果你给this添加属性时,对于一个不存在的对象添加属性,它是会报错的,可自行测试。譬如20kb的exe,这个主程序只是一个框架,它可能仅包含一个主窗休、初始化一些应用需要的全局结构或变量、实现动态装入和卸载包的代码,后面至少带一个被重新编译的vcl包,当然,这个vcl包可能包含所有的delphi提供的标准单元perl scalar函数,也可以仅包含你的应用需要的单元。

词法变量(lexical variable)使用关键字 my声明, 作用域有限, 且不会被存入 符号表.

符号表类似于一个哈希表, 只是类似, 并不完全相同. 我们可以使用 keys关键字来查询其中保存的内容, 比如:

foreach (keys %main::) {
    print $_ . "\n";
}

如果有定义 package 的名字, 则可以样查看:

package Foo;
foreach (keys %Foo::) {
    print $_ . "\n";
}

其中的 %main::和 %Foo::都是符号表.

基于此, 我们使用 keys可以观察一下使用 our和 my声明的变量的不同:

our:

package Foo;
our $bar;
# infact, it will also print "bar" if we declare $bar by using local
# local $bar;
# this will print "bar"
foreach (keys %Foo::) {
    print $_ . "\n";
}

my:

package Foo;
my $bar;
# this will print nothing
foreach (keys %Foo::) {
    print $_ . "\n";
}

perl fork函数_perl数组函数_perl scalar函数

可以很明显的发现, 使用 our声明的变量会被加入符号表 %Foo::, 而使用 my声明的变量则不会. 这是这两种声明方法比较大的区别: 一个声明的是 软件包变量, 存在于 符号表中, 另一个声明的是 词法变量, 不会存在于 符号表.

其实前面提到了 our和 local声明的变量属于一类, 都属于软件包变量, 而 my声明的属于另一类, 叫做词法变量, 但是他们的关系还是有点复杂, 举些例子来分析和理解.

一. 重复使用 our声明变量会覆盖前面的变量, 即使是在新的作用域中:

our $foo = 1;
{
    our $foo = 2;
}
print $foo; # now $foo is 2

二. 在新的作用域中使用 local和 my不会影响原作用域中的变量:

our $foo = 1;
{
    local $foo = 2;
}
print $foo; # $foo is still 1
########################
our $foo = 1;
{
    my $foo = 2;
}
print $foo; # $foo is still 1

在这里看起来 local和 my的表现形式又很类似了, 让人比较迷惑, 其实他们还是有很大区别的, 继续举例子说明.

三. local会在新作用域中暂时改变符号表中的变量值, 直到作用域退出. 而 my创建的变量由于不存在于符号表中, 所以不会影响符号表中的同名变量:

our $foo = 1;
sub print_val {
    print $foo;
}
{
    local $foo = 2;
    print_val(); # this will print 2
}
########################
our $foo = 1;
sub print_val {
    print $foo;
}
{
    my $foo = 2;
    print_val(); # this will print 1
}

分析下上面的例子, 在我们调用了一个函数来打印 $foo的值的时候, 情况又发生了一些变化.

首先, 我们在函数 print_val中打印的 $foo肯定是 our $foo声明出来的. 注意一点, our和 local声明的变量都存在于 符号表中, 可以认为他们就是同一个变量. local的效果就是在新的作用域中, 暂时把外部的变量的值保存起来, 然后把符号表中该变量的值设置为新的值, 等到作用域退出后, 将保存的值恢复到符号表中. 所以在我们使用 local $foo = 2将 $foo重新赋值为 2 以后, print_val函数打印出来的 $foo也变成了 2. 因为他们都是 软件包变量, 而且在新的作用域中, 它已经被暂时替换为了 1.

而第二种写法使用 my声明变量的时候, 注意它声明出来的是 词法变量, 并不存在于符号表中, 所以可以认为此时的 $foo跟外部使用 our $foo声明的变量 $foo毫无关系, 根本就是两个变量. 所以我们当把这个词法变量 $oo声明出来且赋值为 2 的时候, 对 软件包变量的 $foo没有任何影响, 自然使用 print_val函数打印 软件包变量$oo的时候依然会打印出最初的值 1 了.

perl fork函数_perl数组函数_perl scalar函数

希望好好研究一下此处的区别.

与 $foo是 scalar, @foo是 array, %foo是 hash一样, *foo是 typeglob. typeglob 也和符号表一样, 类似于一个哈希表但是却不是一个哈希表, 只是行为有些类似.

我们可以从中取值但是不能对其赋值:

$foo = *foo{SCALAR};
@foo = *foo{ARRAY};
%foo = *foo{HASH};
*foo{SCALAR}   = 5; # error
*foo{WHATEVER} = 5; # error

而且我们不能通过 keys来查看 typeglob 中到底有哪些键名:

print keys *foo; # Experimental keys on scalar is now forbidden

实际上, typeglob 中的键名只有如下几种, 是固定不可变的:

键值变量写法说明

SCALAR

标量

ARRAY

数组

perl scalar函数_perl fork函数_perl数组函数

哈希

&foo

函数

文件句柄

typeglob

FORMAT

报表的格式

变量的名字

PACKAGES

包的名字

我们可以通过把变量的 typeglob 赋值给另一个变量的 typeglob 来创建变量的别名.

创建别名的时候也有两种方式, 一种是创建了完全的别名, 即上一节提到的全部键值对应的部分都成为了别名. 另一种是创建部分别名, 将某个变量的引用赋给另一个变量的 typeglob, 那么只有这个类型的变量创建了别名:

perl scalar函数_perl数组函数_perl fork函数

*foo =  *bar; # full alias
*foo = \$bar; # partial alias

而且除了"完全别名"和"部分别名"这个不同以外, 他们还有一些微妙的区别, 此处需要结合最初讲到的 local等内容来举例说明:

our $bar = 1;
*foo = *bar;
{
    local $bar = 2;
    print $foo; # this will print 2
}
########################
our $bar = 1;
*foo = \$bar;
{
    local $bar = 2;
    print $foo; # this will print 1
}

发现了吗, 在新的作用域中, "完全别名"的写法会受到 local的影响, 而"部分别名"的写法不会受到 local的影响.

我们可以通过打印各个变量的内存地址的方式来看看 local的时候发生了什么, 而使用"完全别名"和"部分别名"两种写法的时候又各自发生了什么.

our $foo;
sub print_val {
    print \$foo . "\n";
}
print \$foo . "\n";     # SCALAR(0x3278c0)
{
    local $foo;
    print \$foo . "\n"; # SCALAR(0x72d430)
    print_val();        # SCALAR(0x72d430)
}

结合我们之前提到的知识, 可以发现, 使用 local的时候, 会在新的作用域中, 创建另一个 软件包变量, 而且能看见使用函数 print_val打印出来的变量地址就是我们 local产生的那个变量的地址, 证明了我们将外部作用域中同名 软件包变量保存了起来, 然后使用新作用域中 local产生的变量替换了这个 软件包变量, 直到作用域退出后恢复以前的那个变量.

继续看:

our $bar;
print \$bar . "\n"; # SCALAR(0x48dfb8)
*foo = *bar;
print \$foo . "\n"; # SCALAR(0x48dfb8)
sub print_val {
    print \$foo . "\n";
}
{
    local $bar;
    print \$bar . "\n"; # SCALAR(0x4fb590)
    print \$foo . "\n"; # SCALAR(0x4fb590)
    print_val();        # SCALAR(0x4fb590)
}

在这种"完全别名"的写法下, 外部作用域中两个变量 $foo和 $bar地址一致, 新作用域中两个变量 $foo和 $bar的地址也一致, 说明 foo一直完全是 bar的别名, 即使外部的值被缓存, 新作用域创建了新的变量 bar, foo依然就是 bar的别名.

然而:

our $bar;
print \$bar . "\n"; # SCALAR(0x327440)
*foo = \$bar;
print \$foo . "\n"; # SCALAR(0x327440)
sub print_val {
    print \$foo . "\n"; # SCALAR(0x327440)
}
{
    local $bar;
    print \$bar . "\n"; # SCALAR(0x8ad430)
    print \$foo . "\n"; # SCALAR(0x327440)
    print_val();
}

使用"部分别名"的写法的时候, foo其实只是外部变量 bar的别名. 在新的作用域中, 我们虽然使用了 local创建了一个新的 $bar, 这会导致新作用域中 $bar会把外部作用域中同名的 $bar隐藏起来, 但是 $foo本身其实只是外部变量的别名, 而且没有同名变量的干扰, 所以不会受到内部 $bar赋值的影响.

以上所述就是小编给大家介绍的《Perl 符号表和 typeglob》,希望对大家有所帮助,如果大家有任何疑问请给我留言perl scalar函数,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-115025-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...