Perl6:NCurses 和鼠标事件

Perl6: NCurses and mouse events

我没有成功从 getmouse 返回鼠标事件。我的代码有错误吗?

#!/usr/bin/env perl6
use v6;
use NCurses;

my $win = initscr;
raw();
keypad( $win, True );
my Array[int32] $old;
mousemask( ALL_MOUSE_EVENTS +| REPORT_MOUSE_POSITION, $old ) or die;

loop {
    my $key = getch();
    if $key == KEY_MOUSE {
        my NCurses::MEVENT $event;
        my $ok = getmouse( $event );
        endwin;
        say "ok:    ", $ok.perl;    # -1
        say "event: ", $event.perl; # NCurses::MEVENT
        exit;
    }
}

NCurses

我找到了缺失的部分:

#!/usr/bin/env perl6
use v6;
use NCurses;

my $win = initscr;
raw();
keypad( $win, True );
my Array[int32] $old;
mousemask( ALL_MOUSE_EVENTS +| REPORT_MOUSE_POSITION, $old ) or die;

loop {
    my $key = getch();
    if $key == KEY_MOUSE {
        my NCurses::MEVENT $event = NCurses::MEVENT.new;
        my $ok = getmouse( $event );
        endwin;
        say "ok:    ", $ok.perl;
        say "event: ", $event.perl;
        exit;
    }
}

一个不太令人敬畏的静默失败掩盖了您正在将类型对象传递到 getmouse() 的事实。我只是通过在第 18 行将 $event.perl 替换为 $event.x 来找到它作为信息钓鱼探险。这样做会产生;

user@Ubuntu-iMac:~$ ./getmouse.p6
ok:    -1
Invocant requires an instance of type NCurses::MEVENT, but a type object was passed.  Did you forget a .new?
  in block  at ./getmouse.p6 line 17

...这只是提供了更多信息。

我相信你现在明白了,但是,为了记录,你输入了 $event 变量但没有给它赋值,所以它得到了根据 Perl6 class tutorial 的类型对象是一个未定义的 "empty instance" 类型。 通过简单地将第 13 行的 my NCurses::MEVENT $event; 替换为 my $event = NCurses::MEVENT.new;,可以得到;

user@Ubuntu-iMac:~$ ./getmouse.p6
ok:    0
event: NCurses::MEVENT.new(id => 0, x => 70, y => 26, z => 0, bstate => 128)

...世界一切都好。

常用成语

如果您必须将类型名称写为变量声明的一部分,您不妨将其写为变量的类型约束并使用 .= new 而不是使用 Marty 或您的解决方案:

my NCurses::MEVENT $event .= new

马蒂的解决方案:

my $event = NCurses::MEVENT.new

起作用是因为 $event 现在包含 getevent($event) 调用需要它包含的内容,即一个新的 NCurses::MEVENT 对象。但是它放弃了一个简单的机会来添加类型检查。

您的解决方案:

my NCurses::MEVENT $event = NCurses::MEVENT.new

的意思与这种情况下的常用习语相同,但不是 DRY

出了什么问题

line of code that glues the Perl 6 getmouse call to the underlying native NCurses library开始:

sub getmouse(MEVENT) ...

这告诉 Perl 6 getmouse 需要一个 NCurses::MEVENT.

类型的参数

马蒂的解决方案奏效了。他们没有告诉 Perl 6 $event 应该包含什么类型的值。但是他们无论如何都会在其中放入正确的值,因此缺少类型检查并不重要。

您的原始解决方案启用了有用的类型检查。它告诉 Perl 6 确保 $event 只包含一个 NCurses::MEVENT 类型的对象。不幸的是,您没有显式初始化变量,因此它包含...

等一下。它包含什么? Perl 6 不应该确保 $event 中有一个 NCurses::MEVENT 对象吗?

事实上它做到了!但是 Perl 6 并没有将 ordinary new NCurses::MEVENT 对象放入其中,而是将旧的 NCurses::MEVENT type 对象放入其中一个占位符。除其他事项外,Type 对象表示未初始化对象的概念。 (有点像 Perl 5 中的“undef”。)

此机制通常适用于出现错误,例如忘记适当地初始化变量。但在这种情况下不是。那到底出了什么问题?

回到getmouse声明。应该是:

sub getmouse(MEVENT:D) ...

:D“type smiley”会告诉 Perl 6 参数必须是 defined,即 uninitialized NCurses::MEVENT 不够好。有了这个笑脸,你会得到一个适当的错误而不是沉默。