"Can't goto subroutine outside a subroutine"

"Can't goto subroutine outside a subroutine"

我创建了一个名为 "MENU" 的子例程,在子例程的顶部有一个名为 "INIT_MENU" 的标签,但是当我调用这个标签时出现错误:Can在 program.pl 行 15

的子例程外不转到子例程

举个例子:

sub MENU {INIT_MENU: print "blah blah";}

这是第 15 行:

goto &MENU, INIT_MENU;

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

goto expects a single argument, so this code first executes goto &MENU and then after the comma operator 它在无效上下文中计算常量 INIT_MENU(绘制警告)。

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

  • Can't goto subroutine outside a subroutine

(F) The deeply magical "goto subroutine" call can only replace one subroutine call for another. It can't manufacture one out of whole cloth. In general you should be calling it out of only an AUTOLOAD routine anyway. See goto.


对此目的的评论。

goto LABELharmfulness写了很多。更何况INIT_MENU:藏在里面找不到例程。结果是总有更好的方法。

采样器

  • 调用函数并传递参数

    MENU(INIT_MENU);
    
    sub MENU {
        my $menu = shift;
        if ($menu eq 'INIT_MENU') { ... }
        ...
    }
    
  • 如果出于某种原因,您想要 'hide' 对 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
    }
    

    这将 top_level() 完全替换为 MENU() 并将其 @_ 传递给它。然后如上所述(例如)处理 MENU 中的输入以触发所选块。在此之后“甚至caller will be able to tell that this routine was called first," see goto。通常不需要

  • 为什么还要MENU()?相反,在单独的 subs 中有菜单选项,它们的引用可以是散列中的值,其中键是选项的名称。所以你会有一个 dispatch table 并且在逻辑(或用户选择)选择一个菜单项之后它的代码是 运行 直接

    my %do_menu_item = ( INIT_MENU => sub { code for INIT_MENU }, ... );
    ...
    $do_menu_item{$item_name}->();
    
  • 菜单系统往往会随着开发变得越来越大和越来越复杂。从一开始就采用 OO 是有意义的,然后还有其他方法可以解决这个细节

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


例如参见 Perl 中的 this post and this post. It's (even) worse than that in Perl since there are specific constructs (and restrictions) for situations where goto can be argued acceptable, so there is even less room for it. One example is jumping out of nested loops: there are labels