Perl函数声明

6mw9ycah  于 2023-01-17  发布在  Perl
关注(0)|答案(2)|浏览(153)

我有这个代码:

1. sub remCH();
2. # Some stuff
3. $line = remCH($line);
4.
5. sub remCH() {
6.     $rem = shift;
7.     $rem = chomp($rem);
8.     return ($rem);
9. }

在执行这段代码时,我总是得到以下错误(第24行在上面的代码中是第3行):
./make_csv.pl第24行“$line)”附近的main::rem_CRLF的参数太多
从我的理解来看,这是因为函数被设置为返回一些东西,但当我声明它时,它被声明为“void”。
如何声明一个如下的函数?

sub remCH(string/integer);
eyh26e7m

eyh26e7m1#

  • 您只需删除第1行中的函数声明(或Perl中的“prototype”)。您的错误是因为prototype(remCH())声明函数具有“零参数”签名,而您的调用传递给它一个参数。返回类型与此无关。

Perl中有一些原型的有效用例,但是除非你知道为什么你要这样设计你的代码,否则经验法则是***永远不要***使用原型。

  • 一个月一次 *
  • 另外,根据plusplus的wise注解,我忽略了第5行函数定义中的“()”。与C不同,在Perl中不需要它们--请删除它们。它们将函数定义变成另一个原型。

话虽如此:

  • 可以使用remCH($) prototype为接受一个标量参数的sub创建原型
  • 通过切换到面向对象的Moose框架,可以让方法检查其类型
6uxekuva

6uxekuva2#

Perl没有类型签名或形参,这与其他语言如C:

// C code
int add(int, int);

int sum = add(1, 2);

int add(int x, int y) {
  return x + y;
}

传统Perl方法

相反,参数只是作为一个平面列表传递,任何类型验证都发生在代码内部;你必须手工编写(见下文),你必须自己把arglist解包成命名变量,而且你通常不会预先声明你的子例程:

my $sum = add(1, 2);

sub add {
  my ($x, $y) = @_; # Unpack arguments
  return $x + $y;
}

如果你预先声明了你的subs,你会得到以下结果:
1.你可以不带括号地调用子函数
1.可以使用“原型”更改解析参数的方式

子例程原型

一个原型可以说

    • 在标量上下文中计算此参数 *:sub foo($),或
    • 此参数必须是散列变量,请将其作为引用传递 *:sub foo(\%),或
    • 此子函数不带参数 *:sub foo()等等。

不要用这些来验证参数的数量,实际上,根本不要用它们;它们会导致远程操作。它们对类型验证也没有用。
你的错误源于你声明了你的sub为空,这导致了一个 parse error

签名

如果希望能够使用命名参数声明子例程,可以使用实现这些参数的模块。

  • 从Perl 5.20开始,您可以使用use feature 'signatures'。它仍然被标记为实验性的,但是基本语法不太可能改变。
use feature 'signatures';
no warnings 'experimental::signatures'

sub add($x, $y) { ... }
  • 有各种各样的CPAN模块,如Method::Signatures,它们可能有集成类型检查的好处,但也可能比用Core Perl实现的解决方案有更多的bug。
use Method::Signatures;

func add(Int $x, Int $y) { ... }

然而,这些“签名”与普通潜艇的原型“毫无关系”。

相关问题