关于现有perl子例程的三个问题

关于现有perl子例程的三个问题,perl,Perl,我试图使用以下perl函数,但我不太清楚三点: sub inittwiddle { my ($m,$n,$aref) = @_; my $i; $$aref[0] = $n+1; for ($i=1; $i != $n-$m+1; $i++) { $$aref[$i] = 0; } while($i != $n+1) { $$aref[$i] = $i+$m-$n; $i++;

我试图使用以下perl函数,但我不太清楚三点:

sub inittwiddle { 
    my ($m,$n,$aref) = @_; 
    my $i; 
    $$aref[0] = $n+1; 
    for ($i=1; $i != $n-$m+1; $i++) { 
       $$aref[$i] = 0; 
    } 
    while($i != $n+1) { 
       $$aref[$i] = $i+$m-$n; 
       $i++; 
    } 
    $$aref[$n+1] = -2; 
    $$aref[1] = 1 if ( $m == 0 ); 
} 
首先,
my($m,$n,$aref)=@代表什么

第二,如何理解像
$$aref[0]=$n+1这样的事物的
$$


这个函数被调用为
inittwidle($M,$N,\@p)p代表什么?

第一个问题只是参数传递。调用perl sub时,其参数位于特殊数组
@
中。第一行只获取数组中的前3项,并将它们放入这3个局部变量中

另外两个问题涉及参考文献。我建议你看一看
\@p
正在将引用传递给数组
@p
。然后,将该引用放入
$$aref
,然后使用
$$aref[0]
访问数组的第一个元素(这可能更清楚地理解为
${$aref}[0]

  • @
    是传递给函数的参数列表。通过执行
    my($m,$n,$aref)=@
    您正在将
    $\u0]
    分配给
    $m
    $\u1]
    分配给
    $n
    $\u2]
    分配给
    $aref

  • $aref
    是一个标量值,包含对数组的引用。要引用数组中的元素,您可以通过
    $aref->[0]
    (这更为惯用),或者通过取消引用数组引用来访问它们。通过在前面添加一个
    @
    ,可以引用数组(即
    @$aref
    )。但是,您需要数组中的第一个元素,它是标量,因此它是通过
    $$aref[0]
    获得的。添加括号(
    ${$aref}[0]
    )或使用箭头符号(
    $aref->[0]
    )可以稍微澄清这一点

  • \@p
    是对数组
    @p
    的引用。由于函数将标量作为第三个参数,因此必须传入标量<代码>\@p
  • 就是这样。当您将数组引用传递到这样的函数中时,请务必注意,对数组的任何更改(例如执行
    $$aref[0]=$n+1
    )都是对原始数组的更改。如果您想避免这种情况,您可以通过执行
    my@tmparr=@$aref在函数中

    首先,
    my($m,$n,$aref)=@代表什么

    将一组参数传递给子例程时,它们将作为列表(有时称为数组)传递给名为
    @
    的特殊数组

    在这种情况下,子例程将变量
    $m
    $n
    $aref
    设置为此特殊数组中的前三个值

    与此类似:

    my $m = @_[0];
    my $n = @_[1];
    my $aref = @_[2];
    

    第二,如何理解像
    $$aref[0]=$n+1这样的事物的
    $$

    现在,我们进入参考文献。引用是指向另一个Perl变量的指针。假设我有一个这样的数组:

    @my_list = ("one", "two", "three", "four");
    
    我可以通过以下操作创建指向此列表的指针:

    my $my_list_ref = \@my_list;
    
    变量
    $my\u list\u ref
    现在指向
    @my\u list
    。变量
    @my_list
    前面的反斜杠告诉Perl,我不想使
    $my_list\u ref
    等于
    @my_list
    。相反,我只希望
    $my_list\u ref
    指向
    @my_list

    现在,如果我想实际引用
    $my_list\u ref
    所指向的数据,我将执行所谓的取消引用操作。我通过在它前面放一个
    @
    来实现:

    print join ",", @{ $my_list_ref };   #prints "one, two, three, four"
    
    如果我想引用列表中
    $my_list_ref
    指向的特定值,我可以使用相同类型的语法:

    print ${ $my_list_ref }[0];   #Prints 'one'
    print ${ $my_list_ref }[1];   #Prints 'two'
    
    将引用变量放在大括号中有助于澄清您在做什么,但同时也会使解析变得更加困难。为了解决这个问题,Perl允许您进行一些语法简化

    在简单情况下,可以删除大括号:

    print $$my_list_ref[0];   #Prints 'one'
    print $$my_list_ref[1];   #Prints 'two'
    
    注意双美元符号!这是您在子例程中看到的

    大多数情况下,您会看到
    ->
    语法,即:


    这个函数被调用为
    inittwidle($M,$N,\@p)什么是
    \@p
    代表的

    现在,我们进入一个问题,为什么首先要使用引用。首先,让我们看一下Perl子程序的一些局限性:

  • 所有参数都在一个
    @
    数组中传递。如果我有一个以两个列表为参数的子程序呢?它们都被咀嚼到单个
    @
    数组中
  • 如果我将一个非常非常大的列表传递到我的子例程中,那么当该列表被复制到
    @
    数组中时,可能会占用大量内存
  • 在Perl子例程中,我传递的所有变量在子例程中都具有独立的标识。在子例程中更改它们不会在它们离开子例程后更改其值。如果我想改变他们的价值观呢
  • 使用引用可以解决所有这些问题。编写此子例程的开发人员试图解决问题2和问题3。电话:

    inittwiddle($M, $N, \@p);
    
    获取两个标量变量,并引用数组
    @p
    。如果数组
    @p
    中有一百万个值,那么将整个列表复制到子例程可能需要很长时间。另外,开发人员看起来也在更改
    @p
    中的项目。当开发者说:

    $$aref[0] = $n + 1;
    
    他实际上正在将
    $p[0]
    更改为
    $n+1
    。当子例程返回时,
    $p[0]
    将具有与子例程之前不同的值。请记住,
    @$aref
    不仅仅是
    @p
    的副本,它指向
    @p
    ,所以它是
    @p


    您应该阅读以了解有关参考的更多信息。

    对于初学者,还需要注意的是,由于
    @p
    是由r传入的
    $$aref[0] = $n + 1;