首页 > 解决方案 > 在实际函数参数中使用 perl `my`

问题描述

我想使用 perl 构建一个尽可能可读的文档图。对于节点的重用,我想使用变量(或常量,如果这样更容易的话)来引用节点。下面的代码工作,并说明了用文字表示的节点类型或对aand的工厂函数调用的想法b。(为了简单的演示目的,这些函数不创建节点,而只是返回一个字符串。)

sub a (@) {
    return sprintf "a(%s)", join( ' ', @_ );
}   

sub b (@) {
    return sprintf "b(%s)", join( ' ', @_ );
}   

printf "The document is: %s\n", a(
    "declare c=",
    $c = 1, 
    $e = b( 
        "use",      
        $c,         
        "to declare d=",
        $d = $c + 1 
    ),      
    "use the result",
    $d,     
    "and document the procedure",
    $e      
);

实际和预期的输出是The document is: a(declare c= 1 b(use 1 to declare d= 2) use the result 2 and document the procedure b(use 1 to declare d= 2)).

出现我的问题是因为我想use strict在整个程序$c中使用. 当然,我可以写在靠近正文顶部的地方。当我可以在第一次提到变量时直接使用关键字时,在编辑时会更有效,如下所示:$d$emymy ( $c, $d, $e );my

…
printf "The document is: %s\n", a(
    "declare c=",
    my $c = 1,
    my $e = b(
        "use",      
        $c,         
        "to declare d=",
        my $d = $c + 1
    ),      
    "use the result",
    $d,     
    "and document the procedure",
    $e      
);

这将是我最喜欢的语法。不幸的是,这段代码产生了几个Global symbol "…" requires explicit package name错误。(此外,根据文档,my不返回任何内容。)

我有这样使用myfrom 使用的想法,例如 inopen my $file, '<', 'filename.txt' or die;或 in for ( my $i = 0; $i < 100; ++$i ) {…}where 声明和定义合二为一。

由于图中的节点是常数,因此可以使用词汇变量以外的其他东西。(但我认为 perl 的内置机制对于词法变量是最强大和最有效的,这就是我倾向于这个方向的原因。)

我目前解决这个问题的想法是定义一个名为类似的函数define,它在幕后将使用PadWalker或类似的方法操纵当前的词汇变量集。然而,这不允许我使用像 perl 这样的自然语法$c = 1,这将是我的首选语法。

标签: perl

解决方案


我不确定确切的需要,但这是进行类似操作的一种简单方法。

OP中的示例希望在函数调用语句本身中有一个命名变量,以便稍后在该语句中用于另一个调用等。如果你必须这样,那么你可以使用一个do块来计算你的参数列表

func1(  
    do { 
        my $x = 5;
        my $y = func2($x);  # etc 
        say "Return from the do block what is then passed as arguments..."; 
        $x, $y
    }
);

这使您可以执行示例所指示的那种事情。

If you also want to have names available in the subroutine then pass a hash (or a hashref), with suitably chosen key names for variables, and in the sub work with key names.

或者,考虑通常在函数调用之前声明变量。虽然有很多好事,但没有坏事。可以放一个小包装纸,让它看起来也不错。


更具体地说

printf "The document is: %s\n", a( do {
    my $c = 1;
    my $d = $c + 1;
    my $e = b( "use", $c, "to declare d=", $d );
    # Return a list from this `do`, which is then passed as arguments to a()
    "declare c=", $c, $e, "use the result", $d,"and document the procedure", $e 
} );

(压缩成更少的行在这里发布)

这个do块是将此代码移入子例程的中途措施,因为我认为有理由希望它内联。但是,由于评论表明现实更加复杂,我敦促您编写一个普通的子程序(顺便说一句,可以在其中构建图表)。


推荐阅读