我更多地出于好奇而尝试了下面的单行,并且感到惊讶的是它实际上没有 %
sigil 。
$ perl -E 'say for keys ::'
适用于版本5.8.8和5.16.3;虽然后一版本会发出此警告:
Hash%::在-e第1行缺少keys()参数中的%。
这怎么工作?即使没有印记,%::
允许它运行和打印密钥有什么特别之处?
请注意,密钥不会打印%main::
。
$ perl -E 'say for keys main::'
Hash main:: missing the % in argument 1 of keys() at -e line 1.
答案 0 :(得分:6)
::
并不特别;在Perl 5.22.0之前,您可以省略%
并将任何标识符传递给keys
。
然而:
keys main::
相当于keys %{'main'}
或仅keys %main
keys ::
相当于keys %{'::'}
或keys %::
。%main
)是{{的别名1}}。相关代码在toke.c中(以下是5.8.8):
%::
/* Look for a subroutine with this name in current package,
unless name is "Foo::", in which case Foo is a bearword
(and a package name). */
if (len > 2 &&
PL_tokenbuf[len - 2] == ':' && PL_tokenbuf[len - 1] == ':')
{
if (ckWARN(WARN_BAREWORD) && ! gv_fetchpv(PL_tokenbuf, FALSE, SVt_PVHV))
Perl_warner(aTHX_ packWARN(WARN_BAREWORD),
"Bareword \"%s\" refers to nonexistent package",
PL_tokenbuf);
len -= 2;
PL_tokenbuf[len] = '\0';
gv = Nullgv;
gvp = 0;
}
else {
len = 0;
if (!gv)
gv = gv_fetchpv(PL_tokenbuf, FALSE, SVt_PVCV);
}
/* if we saw a global override before, get the right name */
if (gvp) {
sv = newSVpvn("CORE::GLOBAL::",14);
sv_catpv(sv,PL_tokenbuf);
}
else {
/* If len is 0, newSVpv does strlen(), which is correct.
If len is non-zero, then it will be the true length,
and so the scalar will be created correctly. */
sv = newSVpv(PL_tokenbuf,len);
}
是当前令牌的长度。
如果令牌为len
,则会创建一个新标量,其PV(字符串组件)设置为main::
。
如果令牌为main
,则会使用::
获取typeglob。
gv_fetchpv
位于gv.c中,具有处理gv_fetchpv
的特殊逻辑:
::
这将获取存储在密钥if (*namend == ':')
namend++;
namend++;
name = namend;
if (!*name)
return gv ? gv : (GV*)*hv_fetch(PL_defstash, "main::", 6, TRUE);
下的default stash中的typeglob(即typeglob main::
)。
最后,*main::
期望它的参数是一个哈希值,但是如果你传递一个标识符,它会将它视为哈希的名称。请参阅op.c中的keys
:
Perl_ck_fun
这也适用于case OA_HVREF:
if (kid->op_type == OP_CONST &&
(kid->op_private & OPpCONST_BARE))
{
char *name = SvPVx(((SVOP*)kid)->op_sv, n_a);
OP * const newop = newHVREF(newGVOP(OP_GV, 0,
gv_fetchpv(name, TRUE, SVt_PVHV) ));
if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX))
Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX),
"Hash %%%s missing the %% in argument %"IVdf" of %s()",
name, (IV)numargs, PL_op_desc[type]);
op_free(kid);
kid = newop;
kid->op_sibling = sibl;
*tokid = kid;
}
else if (kid->op_type != OP_RV2HV && kid->op_type != OP_PADHV)
bad_type(numargs, "hash", PL_op_desc[type], kid);
mod(kid, type);
break;
以外的其他内容:
::
(As of 5.22.0,您不再允许省略$ perl -e'%h = (foo => "bar"); print for keys h'
foo
sigil。)
你也可以用B :: Concise看到这个:
%
答案 1 :(得分:0)
使用:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
/*
* forget about the program name.
*/
argv++;
argc--;
int i;
unsigned int totalNumbers = 0;
printf("Total number of arguments: %d\n", argc);
for(i = 0; i < argc; i++) {
printf("argv[%d]=%s\n", i, argv[i]);
errno = 0;
long num = strtol(argv[i], NULL, 10);
if(!(num == 0L && errno == EINVAL))
totalNumbers++;
}
printf("Total number of numeric arguments: %u\n",
totalNumbers);
return 0;
}
说:
perl -MO=Deparse -E 'say for keys ::'
因此它在没有严格
的perl版本中对待:: as%::