"无法在子程序之外转到子程序"

Gug*_*ira 1 perl label goto subroutine

我已经创建了一个名为"MENU"的子程序,在子程序的顶部有一个名为"INIT_MENU"的标签,但是当我调用这个标签时我得到一个错误:无法在program.pl第15行的子程序之外转到子程序

这是一个例子:

sub MENU {INIT_MENU: print "blah blah";}
Run Code Online (Sandbox Code Playgroud)

这是第15行:

goto &MENU, INIT_MENU;
Run Code Online (Sandbox Code Playgroud)

很抱歉,如果这是一个重复的问题,我搜索了所有可能的地方,甚至在Perl的官方网站

zdi*_*dim 6

转到希望的单个参数,因此,此代码首先执行goto &MENU,然后将后逗号运算它计算常数INIT_MENU在无效的情况下(绘制一个警告).

目的goto &NAME是用子程序替换遇到它的子程序NAME; 在子程序之外调用它是没有意义的,这是一个错误.来自perldiag

  • 无法转到子程序外的子程序

(F)深刻神奇的"goto子程序"调用只能替换另一个子程序调用.它不能用整块布制造一块.通常,您应该仅使用AUTOLOAD例程调用它.见goto.


评论此目的.

已经写了很多关于有害性的文章goto LABEL.更不用说INIT_MENU:隐藏在例程中时无法找到.结果是总有其他更好的方法.

一个采样器

  • 调用该函数并传递参数

    MENU(INIT_MENU);
    
    sub MENU {
        my $menu = shift;
        if ($menu eq 'INIT_MENU') { ... }
        ...
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果出于某种原因,您希望"隐藏" 要按预期MENU使用的呼叫goto &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
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这完全取代了top_level()MENU()并将其@_给它.然后MENU如上所述处理输入(例如)以触发所选择的块.在此之后" 甚至连调用者都无法告诉该例程被称为第一个 ",请参阅goto.但这通常是不必要的.

  • 为什么甚至有MENU()?相反,在单独的subs中有菜单选项,它们的引用可以是散列中的值,其中键是选项的名称.所以你有一个调度表,在逻辑(或用户选择)选择一个菜单项后,它的代码直接运行

    my %do_menu_item = ( INIT_MENU => sub { code for INIT_MENU }, ... );
    ...
    $do_menu_item{$item_name}->();
    
    Run Code Online (Sandbox Code Playgroud)
  • 菜单系统往往随着开发而变得越来越大,越来越复杂.从一开始就采用OO是有意义的,然后还有其他方法来处理这个细节.

如果您发现自己正在考虑goto,可能是时候重新考虑(某些)设计了.


例如,请参阅此帖此帖.它在Perl中(甚至)更糟,因为对于goto可以认为可以接受的情况,存在特定的构造(和限制).一个例子是跳出嵌套循环:Perl中有标签.