子程序/功能参数的数据类型?

时间:2012-09-25 11:29:23

标签: perl

在Perl中,可以为子程序的参数指定一种数据类型吗?例如。在数字上下文中使用dualvar时,例如exit:

use constant NOTIFY_DIE_MAIL_SEND_FAILED       => dualvar 3, 'NOTIFY_DIE_MAIL_SEND_FAILED';
exit NOTIFY_DIE_MAIL_SEND_FAILED;

在这种情况下Perl如何知道,退出需要一个数字参数?我没有看到为子程序的参数定义数据类型的方法,就像在Java中一样? (在那里我可以理解数据类型是如何知道的,因为它是明确定义的)

6 个答案:

答案 0 :(得分:2)

在Perl中,标量同时是数字和字符串。区分字符串和数字不是变量本身,而是您使用的运算符。虽然添加+仅使用数字,但连接.仅使用字符串。

更强类型的语言,例如Java,加法运算符兼作加法和连接运算符,因为它可以访问类型信息。

"1" + 2 + 3在Java中仍然生病,而Perl可以清楚地区分"1" + 2 + 3 == 6"1" . 2 . 3 eq "123"

您可以通过添加0或连接空字符串来强制变量的数字或字符串上下文:

sub foo {
  my ($var) = @_;
  $var += 0;  # $var is numeric
  $var .= ""; # $var is stringy now
}

答案 1 :(得分:2)

双变量的全部意义在于它根据您的需要表现为数字或文本。在那些不明显的情况下(对你来说比对perl更重要)然后说清楚。

exit 0 + NOTIFY_DIE_MAIL_SEND_FAILED;

至于显式输入参数,这不是内置的.Perl是一种比Java更动态的语言,因此检查/强制每个参数或变量的类型并不常见。特别是,perl sub可以接受不同数量的参数甚至不同的结构。

如果您想验证参数(例如,对于外部API),请尝试Params::Validate

之类的内容

此外,MooseMoo允许一定程度的属性输入甚至强制。

答案 2 :(得分:1)

Perl与Java完全不同 - Perldynamically typed语言,因为它不要求在compile time处输入变量。 鉴于,Javastatically typed(如您所知)

Perl根据使用的context确定变量的类型。

只能two context: -

  • 列出上下文
  • 标量上下文

上下文由使用的operatorfunction定义..

对于EG: -

# Define a list
@arr = qw/rohit jain/; 

# Define a scalar
$num = 2

# Here perl will evaluate @arr in scalar context and take its length..
# so, below code will evaluate to : - value = 2 / 2
$value = @arr / $num;

# Here since it is used with a foreach loop, @arr will be taken as in list context
foreach (@arr) {
    say $_;
}
# Above foreach loop will output: - `rohit` \n `jain` to the console..

答案 3 :(得分:1)

您可以通过以下方式强制输入类型:

use Scalar::Util qw(dualvar);
use constant NOTIFY_DIE_MAIL_SEND_FAILED => dualvar 3, 'NOTIFY_DIE_MAIL_SEND_FAILED';
say NOTIFY_DIE_MAIL_SEND_FAILED;
say int(NOTIFY_DIE_MAIL_SEND_FAILED);

<强>输出:

NOTIFY_DIE_MAIL_SEND_FAILED
3

答案 4 :(得分:1)

  

在这种情况下Perl如何知道,退出需要一个数字参数?

退出期望一个数字作为其规范的一部分,如果你传递一个非整数值,它的行为有点未定义(即你不应该这样做。

现在,在这种特殊情况下, dualvar 如何根据上下文设置返回值类型?

我不知道Scalar :: Util的 dualvar 是如何实现的,但你可以用overload编写类似的内容。

您当然可以修改受祝福对象的行为:

#!/usr/bin/env perl

use strict;
use warnings;

{package Dualvar;

use overload
    fallback => 1,
    '0+' => sub { $_[0]->{INT_VAL} },
    '""' => sub { $_[0]->{STR_VAL} };

sub new {
  my $class = shift;
  my $self = { INT_VAL => shift, STR_VAL => shift };
  bless($self,$class);
}

1;
}

my $x = Dualvar->new(31,'Therty-One');

print $x . " + One = ",$x + 1,"\n";    # Therty-One + One = 32

从文档中,似乎重载实际上改变了声明范围内的行为,因此您应该能够在本地更改任何操作数的某些公共运算符的行为。

如果退出确实使用其中一个可重载操作将其参数计算为整数,那么此解决方案就可以。

  

我没有看到为子程序的参数定义数据类型的方法,就像在Java中一样?

正如其他人已经说过的那样......在Perl中并非如此,至少在编译时不是这样,除了子例程prototypes,但是它们没有提供太多的类型粒度(比如int vs strings或者不同)对象类)。

Richard已经提到了一些你可能会使用的运行时替代品。如果您不介意性能损失,我个人会推荐 Moose

答案 5 :(得分:0)

Rohit Jain所说的是正确的。希望输入遵循某些规则的函数只需要明确检查输入是否有效。

例如

sub foo 
{
    my ($param1,$param2) = shift;
    $param1 =~ /^\d+$/ or die "Parameter 1 must be a positive integer.";
    $param2 =~ /^(bar|baz)$/ or die "Parameter 2 must be either 'bar' or 'baz'";

    ...
}

这可能看起来很痛苦,但是:

  • 获得的额外灵活性通常超过了这样做所涉及的工作。
  • 简单地使用正确的数据类型通常不足以确保您有效输入,因此即使使用Java等语言,您最终也会做很多事情。