gpt4 book ai didi

perl - 有没有办法在Perl中强制无效上下文?

转载 作者:行者123 更新时间:2023-12-04 22:12:08 26 4
gpt4 key购买 nike

我想知道这仅仅是出于对Perl工作方式的好奇,以及您对这种事情可以走多远。

有一些函数被编写为在这三种上下文中的每一种上具有不同的作用。

用下面的代码作为一个非常简单的示例:

use 5.012;

say context();
say scalar context();

sub context {
if (wantarray) {
return 'list';
} elsif (defined wantarray) {
return 'scalar';
} else {
return 'void'; # Destined to be discarded
}
}

输出:
list
scalar

您能想到一种方法来在调用 say后激发第三个 void并输出 context()的方法吗?

我知道这是一个矛盾,因为无效的上下文可能意味着您并没有真正返回/分配任何东西。但是,据我从Perl的工作方式中了解到的,并不是返回任何内容,而是在void上下文中执行完之后,返回值将被丢弃。

因此,我想知道:是否有一种方法可以强制无效上下文作为 的上下文,而您在调用函数时恰好实际上位于列表或标量上下文中呢?

最佳答案

sub void(&) { $_[0]->(); () }

say context();
say scalar context();
say void { context() };

更高级的代码可以为我们提供更好的语法:
use syntax qw( void );

say context();
say scalar context();
say void context();

顺便说一句,以下内容表明 scalar与其说是一个编译时指令,不如说是一个函数:
$ diff -u0 \
<( perl -MO=Concise,-exec -Msyntax=void -E'say f()' 2>&1 ) \
<( perl -MO=Concise,-exec -Msyntax=void -E'say scalar f()' 2>&1 )
--- /dev/fd/63 2014-08-17 12:34:29.124827443 -0700
+++ /dev/fd/62 2014-08-17 12:34:29.128827401 -0700
@@ -7 +7 @@
-6 <1> entersub[t6] lKS/TARG <-- "l" for list context
+6 <1> entersub[t7] sKS/TARG <-- "s" for scalar context

use syntax qw( void ) void也是如此:
$ diff -u0 \
<( perl -MO=Concise,-exec -Msyntax=void -E'say f()' 2>&1 ) \
<( perl -MO=Concise,-exec -Msyntax=void -E'say void f()' 2>&1 )
--- /dev/fd/63 2014-08-17 12:34:41.952692723 -0700
+++ /dev/fd/62 2014-08-17 12:34:41.952692723 -0700
@@ -7 +7 @@
-6 <1> entersub[t6] lKS/TARG <-- "l" for list context
+6 <1> entersub[t6] vKS/TARG <-- "v" for void context
use syntax qw( void );如何工作

实际工作由 Syntax::Feature::VoidVoid.xs完成,其关键行如下:
STATIC OP* parse_void(pTHX_ GV* namegv, SV* psobj, U32* flagsp) {
return op_contextualize(parse_termexpr(0), G_VOID);
}

STATIC OP* ck_void(pTHX_ OP* o, GV* namegv, SV* ckobj) {
return remove_sub_call(o);
}

BOOT: {
const char voidname[] = "Syntax::Feature::Void::void";
CV* const voidcv = get_cvn_flags(voidname, sizeof(voidname)-1, GV_ADD);
cv_set_call_parser(voidcv, parse_void, &PL_sv_undef);
cv_set_call_checker(voidcv, ck_void, &PL_sv_undef);
}
  • 它使用void声明子get_cvn。 (永远不会定义该子项。)Void.pm中的代码会将子项导出到调用的词法作用域。
  • 它告诉Perl,对void的调用遵循使用cv_set_call_parser的用户定义语法。
  • 它告诉Perl,使用void编译对cv_set_call_checker的调用后,需要对其进行操作。
  • 当Perl遇到对void的调用时,用户定义的解析器使用parse_termexpr提取一个术语,然后使用void将术语的上下文更改为op_contextualize
  • 之后,检查器将从操作码树中删除对void的调用,同时保留其自变量(术语)。
  • 关于perl - 有没有办法在Perl中强制无效上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25349523/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com