是否允许将管道传递给构造函数? [英] is it allowed to pass pipes to constructors?

查看:40
本文介绍了是否允许将管道传递给构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用 Perl 做一些非常奇特的事情,但我想我正在承受后果.实际上,我不知道我尝试做的事情是否可行.

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

pipe(my $pipe_reader, my $pipe_writer);

(最初它是 pipe(PIPE_READER, PIPE_WRITER) 但当我试图调试它时我改为常规变量)

然后它分叉,但我认为这在这里可能无关紧要.孩子这样做:

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

Response 的构造函数很简单:

sub new {我的 $class = shift;我的 $writer = shift;我的 $self = {作家 =>$作者};祝福($self,$class);返回($self);}

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

$response->respond(123, "这是我的回复");

响应代码如下:

子响应{我的 $self = shift;我的 $number = shift;我的 $text = shift;打印 $self->{writer} "$number\n";打印 $self->{writer} "$text\n";关闭 $self->{writer}}

这会触发一个奇怪的编译错误:'String found where operator expected ... Missing operator before "$number\n"?'在第一次打印时.当然,这是打印的正常语法,除了我有对象属性而不是普通句柄并且它恰好是管道,而不是文件句柄.所以现在我想知道是否不允许我这样做.

解决方案

来自 print

<块引用>

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

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

(我的重点)

所以你需要

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


或者,根据 Borodin 的评论

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

print 的语法比较特殊,参见例如这篇文章这篇文章.首先,在 print 之后必须是一个简单的"如上所述,文件句柄或求值为 1,以满足解析器的要求.

但是使用 取消引用(箭头)运算符 找到了文件句柄成为一个 IO::File 对象 等等对它调用父级的 IO::Handle::print 方法.在 v5.14 之前,必须 use IO::Handle; 才能使其工作,尽管现在不再如此.请参阅这篇文章及其中的链接以了解更多信息.

请注意,print FILEHANDLE LIST 不是 间接方法调用,即使它看起来如此.它只是在相当特殊的语法规则下对内置的 print 的函数调用.它只有一个显式的 ->IO::Handle 方法被调用.


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

perl -MScalar::Util=blessed -wE'管道(RD,WR);说*WR{IO};#-->IO::文件=IO(0xe8cb58)说有福的(WR)//undef";#-->未定义'

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

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

I tried to do something very fancy in Perl, and I think I'm suffering the consequences. I don't know if what I was trying to do is possible, actually.

My main program creates a pipe like this:

pipe(my $pipe_reader, my $pipe_writer);

(originally it was pipe(PIPE_READER, PIPE_WRITER) but I changed to regular variables when I was trying to debug this)

Then it forks, but I think that is probably irrelevant here. The child does this:

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

The constructor of Response is bare bones:

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

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

Then later the child will write its response:

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

The code for respond is as follows:

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

This triggers a strange compile error: 'String found where operator expected ... Missing operator before "$number\n"?' at the point of the first print. Of course this is the normal syntax for a print, except that I have the object property instead of a normal handle AND it happens to be a pipe, not a file handle. So now I'm wondering if I'm not allowed to do this.

解决方案

From print

If you're storing handles in an array or hash, or in general whenever you're using any expression more complex than a bareword handle or a plain, unsubscripted scalar variable to retrieve it, you will have to use a block returning the filehandle value instead, ...

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

(my emphasis)

So you need

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


Or, per Borodin's comment

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

The syntax of print is special, see for example this post and this post. For one, after print must come either a "simple" filehandle or a block evaluating to one, as quoted above, to satisfy the parser.

But with the dereference (arrow) operator the filehandle is found to be an IO::File object and so its parent's IO::Handle::print method is invoked on it. Prior to v5.14 there had to be use IO::Handle; for this to work, though not anymore. See this post and links in it for more.

Note that print FILEHANDLE LIST is not an indirect method call, even as it may appear to be. It is just a function call to the print builtin under rather special syntax rules. It is only with an explicit -> that an IO::Handle method gets called.


It is either blessed into the class as the method call is encountered (and fails), or at creation; I can't find it in docs or otherwise resolve whether filehandles are blessed at creation or on demand

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

(warns of unused RD)   We can't do this with lexical filehandles as they are not in the symbol table.

But once needed a filehandle is an IO::File or IO::Handle object (depending on Perl version).

这篇关于是否允许将管道传递给构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆