我在子程序的頂部創建了一個名爲「MENU」的子程序,名稱爲「INIT_MENU」,但當我打電話給該標籤時出現錯誤:Can的子程序以外「噸轉到子程序在program.pl線15「子程序外不能轉到子程序」
下面是一個例子:
sub MENU {INIT_MENU: print "blah blah";}
和這裏是線15:
goto &MENU, INIT_MENU;
很抱歉,如果它是一個重複的問題,我搜索在所有可能的地方,甚至在Perl
我在子程序的頂部創建了一個名爲「MENU」的子程序,名稱爲「INIT_MENU」,但當我打電話給該標籤時出現錯誤:Can的子程序以外「噸轉到子程序在program.pl線15「子程序外不能轉到子程序」
下面是一個例子:
sub MENU {INIT_MENU: print "blah blah";}
和這裏是線15:
goto &MENU, INIT_MENU;
很抱歉,如果它是一個重複的問題,我搜索在所有可能的地方,甚至在Perl
的goto只需要一個論證的官方網站,所以這段代碼後的第一個執行goto &MENU
然後comma operator它在無效的上下文中評估常量INIT_MENU
(繪製警告)。
goto &NAME
的作用是用子程序NAME
替換遇到的子程序;在子程序之外調用它是沒有意義的,這是一個錯誤。從perldiag
- 能子程序
(F)之外沒有轉到子程序的深深神奇的「轉到子程序」呼叫只能更換一個子程序調用另一個。它不能用整塊布來製造。總的來說,無論如何,你應該只從一個AUTOLOAD例程中調用它。請參閱goto。
上的這個用途的註釋。
在goto LABEL
的harmfulness上寫了很多。 †更不用說,當隱藏在例程中時,找不到INIT_MENU:
。結果是總有其他更好的方法。
採樣器
調用函數如果由於某種原因,你想 '隱藏' 如預期
調用MENU
使用goto &MENU
傳遞參數 MENU(INIT_MENU);
sub MENU {
my $menu = shift;
if ($menu eq 'INIT_MENU') { ... }
...
}
sub top_level { # pass INIT_MENU to this sub
...
goto &MENU; # also passes its @_ as it is at this point
# the control doesn't return here; MENU took place of this sub
}
這完全取代了top_level()
與MENU()
並將它的@_
傳遞給它。然後如上所述處理輸入MENU
(例如)以觸發所選塊。在此之後,「甚至不會caller將能夠告訴該例程被稱爲第一,」見goto。但這通常是不需要的。
爲什麼即使有MENU()
?相反,在單獨的子文件中有菜單選項,並且它們的引用可以是散列中的值,其中鍵是選項的名稱。所以,你就會有一個分派表和邏輯(或用戶選擇)後,選擇其代碼運行的菜單項直接
my %do_menu_item = (INIT_MENU => sub { code for INIT_MENU }, ...);
...
$do_menu_item{$item_name}->();
菜單系統往往具有發展壯大規模,更復雜。從一開始就採用面向對象是有意義的,然後還有其他方法可以用於這個細節。
如果你發現自己考慮goto
可能是時候重新考慮(一些)的設計。
†參見例如this post和this post。它在Perl中甚至更糟糕,因爲對於goto
可以被認爲是可接受的情況,存在特定的構造(和限制)。一個例子是跳出嵌套循環:Perl中有labels。
調度表的另一種替代方法是OO多態性。 – shawnhcorey
goto中尾隨的INIT_MENU
是紅鯡魚 - 它在無效的情況下; Perl會發出警告,然後拋開價值。
問題出在goto &MENU
。這是一個不可思議的轉換,它將用調用的子程序替換當前的子程序。這裏的實質是替換當前的子程序。
您的代碼在子程序之外調用goto &MENU
,所以沒有當前的子程序被替換。 正好是錯誤信息描述的內容。
看起來沒有足夠的信息可用。試着看看你是否可以創建一個小例子。 – Suren
這裏是[示例的完整源代碼](https://pastebin.com/UWENBXZp),一個簡單的程序。 –
我不知道你爲什麼要這樣做,你可以刪除塊標籤並調用你的MENU()。除非你知道你在做什麼(以及爲什麼),否則你可能不需要使用典型的Perl代碼中的'goto'。 – xxfelixxx