2016-02-19 78 views
3

我沒有成功從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

回答

2

一個低於真棒無聲故障屏蔽您傳遞一個類型的對象到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

1

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

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

常用的成語

如果你必須寫一個類型的名字作爲一個變量聲明的一部分,你還不如把它寫成變量的類型約束和使用.= 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