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

Ste*_*hen 3 perl

我试图在Perl中做一些非常奇特的事情,我想我正在遭遇后果.实际上,我不知道我想做的事情是否可行.

我的主程序创建了这样的管道:

pipe(my $pipe_reader, my $pipe_writer);
Run Code Online (Sandbox Code Playgroud)

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

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

my $response = Response->new($pipe_writer);
Run Code Online (Sandbox Code Playgroud)

Response的构造函数是简单的:

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

    my $self = {
        writer => $writer
    };
    bless($self, $class);
    return($self);
 }
Run Code Online (Sandbox Code Playgroud)

然后孩子会写下它的回答:

$response->respond(123, "Here is my response");
Run Code Online (Sandbox Code Playgroud)

回复代码如下:

sub respond {
    my $self = shift;
    my $number = shift;
    my $text = shift;
    print $self->{writer} "$number\n";
    print $self->{writer} "$text\n";
    close $self->{writer}
}
Run Code Online (Sandbox Code Playgroud)

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

zdi*_*dim 9

印刷品

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

print { $files[$i] } "stuff\n";
print { $OK ? *STDOUT : *STDERR } "stuff\n";
Run Code Online (Sandbox Code Playgroud)

(我的重点)

所以你需要

print { $self->{writer} } "$number\n";
Run Code Online (Sandbox Code Playgroud)

或者,根据鲍罗丁的评论

$self->{writer}->print("$number\n");
Run Code Online (Sandbox Code Playgroud)

语法print很特殊,请参阅此帖子这篇文章.首先,print必须来一个"简单"的文件句柄或一个评估为一个的块(如上所述,参见文档),以满足解析器.

但是使用取消引用(箭头)运算符,文件句柄被发现是一个IO :: File对象,因此在其上调用其父级的IO :: Handle :: print方法.在v5.14之前,必须有use IO::Handle;这个工作,但不再是.有关更多信息,请参阅此文章及其中的链接.

请注意,这print FILEHANDLE LIST不是间接方法调用,即使它看起来像是.它只是print在相当特殊的语法规则下对内置函数的函数调用.只有明确-> 表示IO::Handle调用方法.


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

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

(警告未使用RD)我们不能用词法文件句柄来做这个,因为它们不在符号表中.

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