是否允许将管道传递给构造函数?

时间:2018-01-27 00:11:26

标签: perl

我试图在Perl中做一些非常有趣的事情,我想我会承受后果。实际上,我不知道我想做什么是可能的。

我的主程序会创建一个这样的管道:

pipe(my $pipe_reader, my $pipe_writer);

(最初它是管道(PIPE_READER,PIPE_WRITER)但我在尝试调试时改为常规变量)

然后它分叉,但我认为这可能与此无关。孩子这样做:

my $response = Response->new($pipe_writer);

Response的构造函数很简单:

sub new {
    my $class = shift;
    my $writer = shift;

    my $self = {
        writer => $writer
    };
    bless($self, $class);
    return($self);
 }

然后孩子会写下答案:

$response->respond(123, "Here is my response");

回复代码如下:

sub respond {
    my $self = shift;
    my $number = shift;
    my $text = shift;
    print $self->{writer} "$number\n";
    print $self->{writer} "$text\n";
    close $self->{writer}
}

这会触发一个奇怪的编译错误:'找到操作符期望的字符串...在" $ number \ n"?'之前缺少运算符在第一次印刷时。当然这是打印的正常语法,除了我有对象属性而不是普通句柄,它恰好是管道,而不是文件句柄。所以现在我想知道我是否不允许这样做。

1 个答案:

答案 0 :(得分:9)

来自print

  

如果您将句柄存储在数组或散列中,或者通常在您使用任何比裸字句柄更复杂的表达式或用于检索它的普通,未取消的标量变量时,您将必须使用一个块返回文件句柄值,而不是......

print { $files[$i] } "stuff\n";
print { $OK ? *STDOUT : *STDERR } "stuff\n";

(我的重点)

所以你需要

print { $self->{writer} } "$number\n";

或者,根据Borodin的评论

$self->{writer}->print("$number\n");

print的语法很特殊,例如请参阅this postthis post。例如,print必须在“简单”文件句柄或评估为一个(如上所述,请参阅文档)之后,以满足解析器。

但是使用dereference (arrow) operator,文件句柄被发现是IO::File对象,因此在其上调用其父级IO::Handle::print方法。 在v5.14之前,必须有use IO::Handle;才能使用它,尽管不再这样了。有关详情,请参阅this post及其中的链接。

请注意,print FILEHANDLE LIST不是indirect method call, 即使它看起来像。它只是在相当特殊的语法规则下对print内置函数的函数调用。它只有一个明确的-> 调用IO::Handle方法。

当遇到(并且失败)方法调用时,或者在创建时,它或者被祝福。我无法在文档中找到它或以其他方式解决文件句柄是在创建时还是在需要时受到祝福

perl -MScalar::Util=blessed -wE'
    pipe(RD,WR);                   
    say *WR{IO};                   #--> IO::File=IO(0xe8cb58)
    say blessed(WR)//"undef";      #--> undef
'

(警告未使用的RD)我们不能使用词法文件句柄来执行此操作,因为它们不在符号表中。

但是一旦需要文件句柄 IO::FileIO::Handle对象(取决于Perl版本)。