Perl6:NCurses和鼠标事件

问题描述:

我没有成功从getmouse返回鼠标事件。我的代码中是否有错误?Perl6: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; 
     my $ok = getmouse($event); 
     endwin; 
     say "ok: ", $ok.perl; # -1 
     say "event: ", $event.perl; # NCurses::MEVENT 
     exit; 
    } 
} 

NCurses

一个低于真棒无声故障屏蔽您传递一个类型的对象到getmouse(事实)。我只在第18行用$event.perl代替$event.x作为信息捕鱼的探险。这样做会产生;

[email protected]:~$ ./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 

...这只是一点点更多的信息。

我敢肯定,你得到它,但现在,对于记录,您输入的$事件变量,但没有任何值分配给它,所以它得到了根据Perl6 class tutorial是一个未定义的类型的对象,“空实例“的类型。 只需在第13行用my $event = NCurses::MEVENT.new;代替my NCurses::MEVENT $event;即可;

[email protected]:~$ ./getmouse.p6 
ok: 0 
event: NCurses::MEVENT.new(id => 0, x => 70, y => 26, z => 0, bstate => 128) 

......和一切都很好的世界。

+0

我已经在我的答案中更正了这一点。 –

+0

是的 - 当发生这种情况时,我正在寻找解决方案并起草我的答案。非常感谢你接受我自己 - 我很高兴你自己找到了它 - 我只是希望你在半小时后就这么做了。 ;-) – Marty

我已经找到了缺失的部分:

#!/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; 
    } 
} 

常用的成语

如果你必须写一个类型的名字作为一个变量声明的一部分,你还不如把它写成变量的类型约束和使用.= new而不是使用任何马蒂或解决方案:

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对象吗?

其实它做到了!但不是把一个普通新的NCurses::MEVENT对象在那里Perl 6把一个旧的NCurses::MEVENT类型对象在那里作为占位符。除此之外,Type对象表示未初始化对象的概念。 (有点像Perl 5中的“undef”。)

这种机制通常适用于像忘记适当初始化变量一样的错误。但不是在这种情况下。那么出了什么问题?

回到getmouse声明。它应该是:

sub getmouse(MEVENT:D) ... 

:D“式的笑脸”会告诉Perl 6中的参数必须是定义,即一个未初始化NCurses::MEVENT不够好。有了这个笑脸,你会得到一个适当的错误而不是沉默。

+0

Raiph - 我想你会发现建议的'sub getmouse(MEVENT:D)'签名和你以前使用'。= new' __时的建议__当进行类型检查时.__我不同意你的意思该类型检查*应该*在任何地方使用。简而言之,几乎没有风险混淆类型和没有获得重大性能收益的小程序并不需要所有的检查和约束,是吗?我们不能偶尔骑在狂野的一面吗? ;-) – Marty

+1

我不是暗示显式类型检查应该到处使用。编码人员可能不关心许多脚本的类型约束。但是,我列出的替代方案与您的解决方案完全相同,没有坏处,是通常的习惯用法,无论如何可能会发生类型错误,即使无关紧要,也可能会加速编码,并为编码器建立正确的编码模式*确实*关心速度或捕捉类型错误。 TIMTOWTDIBSCINABTE。 :) – raiph