Perl递归和函数

Chr*_*ris 2 perl loops recursive-query

听说Perl一年后,我决定给它几个小时的时间来看看我能拿到多少.我完成了基础知识,然后进入循环.作为测试,我想看看是否可以构建一个脚本来递归所有最多4个字符的字母数字值.我写了一段PHP代码,前一段时间做了同样的事情所以我采用了相同的概念并使用它.然而,当我运行脚本时,它将"a"作为前3个值,然后仅循环通过最后一个数字.有谁看到我做错了什么?

#!/usr/local/bin/perl 

$chars = "abcdefghijklmnopqrstuvwxyz";
$chars .= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$chars .= "0123456789";

@charset = split(//, $chars);

$charset_length = scalar(@charset);

sub recurse
{
 ($width, $position, $base_string) = @_;

for ($i = 0; $i < $charset_length; ++$i) {
    $base = $base_string . $charset[$i];
    if ($position < $width - 1) {
        $pos = $position + 1;
        recurse($width, $pos, $base);
    }
    print $base;
    print "\n";
}
}

recurse(4, 0, '');
Run Code Online (Sandbox Code Playgroud)

这是我运行时得到的:

aaaa
aaab
aaac
aaad
aaae
aaaf
aaag
aaah
aaai
aaaj
aaak
aaal
aaam
aaan
aaao
aaap
aaaq
aaar
aaas
aaat
aaau
aaav
aaaw
aaax
aaay
aaaz
aaaA
aaaB
aaaC
aaaD
aaaE
aaaF
aaaG
aaaH
aaaI
aaaJ
aaaK
aaaL
aaaM
aaaN
aaaO
aaaP
aaaQ
aaaR
aaaS
aaaT
aaaU
aaaV
aaaW
aaaX
aaaY
aaaZ
aaa0
aaa1
aaa2
aaa3
aaa4
aaa5
aaa6
aaa7
aaa8
aaa9
aaa9
aaa9
aaa9
Run Code Online (Sandbox Code Playgroud)

Joh*_*ehm 11

你已经被非严格的范围所困扰了,这段代码做了它应该做的事情(注意顶部使用strict和后续使用我来保证变量作用域).

#!/usr/bin/env perl
use strict;
use warnings;

my $chars = "abcdefghijklmnopqrstuvwxyz";
$chars .= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$chars .= "0123456789";

my @charset = split(//, $chars);

my $charset_length = scalar(@charset);

sub recurse {
    my ($width, $position, $base_string) = @_;

    for (my $i = 0; $i < $charset_length; ++$i) {
        my $base = $base_string . $charset[$i];

        if ($position < $width - 1) {
            my $pos = $position + 1;
            recurse($width, $pos, $base);
        }

        print $base;
        print "\n";
    }
}

recurse(4, 0, '');
Run Code Online (Sandbox Code Playgroud)


yst*_*sth 10

已经得到很好的回答,但更惯用的方法是:

use strict;
use warnings;

sub recurse {
    my ($width, $base_string, $charset) = @_;

    if (length $base_string) {
        print "$base_string\n";
    }
    if (length($base_string) < $width) {
        $recurser->($base_string . $_) for @$charset;
    }
}

my @charset = ('a'..'z', 'A'..'Z', '0'..'9');
recurse(4, '', \@charset);
Run Code Online (Sandbox Code Playgroud)

没有必要通过位置; 它隐含在传入的基本字符串的宽度中.另一方面,charset应该被传入而不是让子例程使用外部变量.

或者,由于宽度和字符集保持不变,因此生成一个引用它们的闭包:

use strict;
use warnings;

sub make_recurser {
    my ($width, $charset) = @_;
    my $recurser;
    $recurser = sub {
        my ($base_string) = @_;

        if (length $base_string) {
            print "$base_string\n";
        }
        if (length($base_string) < $width) {
            $recurser->($base_string . $_) for @$charset;
        }
    }
}

my @charset = ('a'..'z', 'A'..'Z', '0'..'9');
my $recurser = make_recurser(4, \@charset);
$recurser->('');
Run Code Online (Sandbox Code Playgroud)

或者,只需:

print "$_\n" for glob(('{' . join(',', 'a'..'z', 'A'..'Z', '0'..'9') . '}') x 4);
Run Code Online (Sandbox Code Playgroud)