首页 > perl函数原型

perl函数原型

CU上的翻译

=head1 prototype



Perl 可以通过函数元型在编译期进行有限的参数类型检验。如果你声明



    sub mypush (+@)



那么 mypush() 对参数的处理就同内置的 push() 完全一样了。函数声明必须要在编译

相应函数调用之前告知编译器(编译器在编译函数调用时会对相应函数用 prototype

来查询它的元型来进行参数检验,并决定怎样编译此函数调用)。元型只在不用 & 调用

函数的时候起作用。就是说在语法上如果你想像内置函数一样调用,它就表现的像

内置函数一样。如果想用过时的风格通过 & 调用,那么编译器就无视函数声明。另外

元型在函数引用如 &foo 和间接调用如 &{$subref} 和 $subref->() 时也不起作用。



方法调用也不受元型影响,因为实际调用的函数无法在编译期决定,它是由继承关系

决定的。



因为这个特性最初的目的是使你可以像内置函数那样调用自己的函数,所以下面就给出

等价于内置函数调用方式的函数元型。



    声明为                  调用方式



    sub mylink ($$)         mylink $old, $new

    sub myvec ($$$)         myvec $var, $offset, 1

    sub myindex ($$;$)      myindex &getstring, "substr"

    sub mysyswrite ($$$;$)  mysyswrite $buf, 0, length($buf) - $off, $off

    sub myreverse (@)       myreverse $a, $b, $c

    sub myjoin ($@)         myjoin ':', $a, $b, $c

    sub mypop (+)           mypop @array

    sub mysplice (+$$@)     mysplice @array, 0, 2, @pushme

    sub mykeys (+)                mykeys %{$hashref}

    sub myopen (*;$)            myopen HANDLE, $name

    sub mypipe (**)                mypipe READHANDLE, WRITEHANDLE

    sub mygrep (&@)                mygrep { /foo/ } $a, $b, $c

    sub myrand (;$)                myrand 42

    sub mytime ()                mytime



任何 跟着的函数元型中的字符代表着实际的参数必须由相应字符开头(参数前可跟

my our local 声明),只有 $ 例外,它可以接收并不以 $ 开头的 hash 和数组的元素,

比如 my_function()->[0]。传给 @_ 的参数将会是相应实际参数的引用,即对它加 。



你可以用 [] 来表示多个可用的类型。比如:



    sub myref ([$@%&*])



上面的函数声明允许像下面这样调用 myref() 这个函数



    myref $var

    myref @array

    myref %hash

    myref &sub

    myref *glob



传入函数 myref 的第一个参数将分别是一个 scalar、数组、hash、函数、glob 的引用。



函数元型中前面不跟 的字符有特殊意义。任何不跟 的 @ % 将代表剩下的所有参数,

并提供 list context。而 $ 将提供 scalar context。 & 表示需要一个匿名函数(即

sub { } 这样的结构,不能是变量),当用作第一个参数时可以省掉 sub 关键字(如果

省掉 sub 则后面跟的逗号也必须要省掉).



* 表明可以接收一个 bareword、常量、scalar 表达式、typeglob或 typeglob 的引用。

传入函数的参数要么是一个简单的 scalar 要么是 typeglob 的引用(后两种情况)。如果

你总是想要一个 typeglob 的引用可以用 Symbol::qualify_to_ref() 将名字转换成相应

的 typeglob 的引用:



    use symbol 'qualify_to_ref';



    sub foo (*) {

        my $fh = qualify_to_ref(shift, caller);

        ...

    }



+ 类似于 $ 但是当遇到数组变量或 hash 变量时表示 [@%],在其它情况下总是提供

scalar context。它适用于可以接收数组变量或数组引用为参数的函数:



    sub mypush (+@) { # 5.14 中 push 第一个参数可以为数组的引用

        my $aref = shift;

        die "Not an arrayref" unless ref $aref eq 'ARRAY';

        push @$aref, @_;

    }



当用 + 时函数必须要检验实际的参数是否是自己需要的类型,因为它不区分 @ %。



分号 ; 用来分隔必须的参数和可选的参数。它必须在 @ % 之前,因为它们代表剩下的

所有参数。



在元型最后或在 ; 之前可以用 _ 来代替 $:它表示如果没有提供这个参数会传递 $_

作为对应的参数,它可以用来实现默认参数的语法。



注意上面列表最后3个例子,mygrep() 表现的就像列表操作符,myrand() 表现的就像

rand() 一样为一元操作符,mytime() 就像 time() 一样完全不需要参数。如果你这么用:



    mytime + 2;



你将会得到 mytime() + 2,而不是 mytime(2),没有函数元型根本无法实现这样的效果。



有意思的是你可以把 & 用在最开始的位置来创造新语法:



    sub try (&@) {

        my ($try, $catch) = @_;

        eval { &$try };

        if ($@) {

            local $_ = $@;

            &$catch;

        }

    }



    sub catch (&) { $_[0] }



    try {

        die "phooey";

    } catch {

        /phooey/ and print "unphooey ";

    };



上面的代码会打印 "unphooey",即是 Try::Tiny 的实现方法。(当然用 &$catch 会

将 @_ 暴露给 $catch 但这里并不是我们要考虑的)。



让我们重新实现下 Perl 的 grep 操作符:



    sub mygrep (&@) { # 无法实现 grep EXPR,LIST 这个语法

        my $code = shift;

        my @result;

        foreach $_ (@_) {

            push @result, $_ if &$code;

        }

        @result;

    }



请不在要函数元型中使用字母或数字,它们被保留作它用,或许在将来用于实现完整的

参数列表。不要为老的代码添加上函数元型,因为有时会改变语意出来奇怪的结果。比如:



    sub func ($) {

        my $n = shift;

        print "you ave me $n ";

    }



某人在代码中这么调用它:



    func(@foo);

    func(split /:/);



只是声明了函数 func 只接收一个 scalar 参数却带来了灾难性的结果,原来参数所处的

list context 被改为 scalar context,传入的参数变成 @foo 的元素个数,和分割的

元素个数。



元型很强大也很危险,请小心慎用。

 

以两个数组为参数的函数原型

sub test(@@) {my ($ref_array1, $ref_array2) = @_;print @{ $ref_array1}, "
";print @{ $ref_array2}, "
";
}my @array1 = (1, 2, 3);
my @array2 = (4, 5, 6);
test(@array1, @array2)

注意调用的时候,不要加&,因为&会忽略所有的函数原型检查。

一般来说,函数原型能实现的功能,用非函数原型都能实现,比如上面的代码用下面的方式也能实现,采用数组的引用。

sub test {my ($array1, $array2) = @_;print @{ $array1}, "
";print @{ $array2}, "
";
}my $array1 = [1, 2, 3];
my $array2 = [4, 5, 6];test($array1, $array2);1;

==

更多相关:

  • 草色新雨中, 松声晚窗里。之前我们学习 Power Query 都是用鼠标就完成了很多复杂的操作。虽然 PowerQuery 已经将大部分常用功能内置成到功能区。基本能完成我们大部分的报表自动化功能。但是总有些复杂的或者个性化的问题是开发团队没有预先想到的,这时我们就需要学习 M 语言。一、M 语言在哪里?M语言的函数公式有三个地...

  • 前言从2020年3月份开始,计划写一系列文档--《小白从零开始学编程》,记录自己从0开始学习的一些东西。第一个系列:python,计划从安装、环境搭建、基本语法、到利用Django和Flask两个当前最热的web框架完成一个小的项目第二个系列:可能会选择Go语言,也可能会选择Vue.js。具体情况待定,拭目以待吧。。。基本概念表达式表...

  • 1.1函数1.1.1什么是函数函数就是程序实现模块化的基本单元,一般实现某一功能的集合。函数名:就相当于是程序代码集合的名称参数:就是函数运算时需要参与运算的值被称作为参数函数体:程序的某个功能,进行一系列的逻辑运算return 返回值:函数的返回值能表示函数的运行结果或运行状态。1.1.2函数的作用函数是组织好的,可重复使用的,用来...

  • 原标题:基于Python建立深度神经网络!你学会了嘛?图1 神经网络构造的例子(符号说明:上标[l]表示与第l层;上标(i)表示第i个例子;下标i表示矢量第i项)单层神经网络图2 单层神经网络示例神经元模型是先计算一个线性函数(z=Wx+b),接着再计算一个激活函数。一般来说,神经元模型的输出值是a=g(Wx+b),其中g是激活函数(...

  • 在学习MySQL的时候你会发现,它有非常多的函数,在学习的时候没有侧重。小编刚开始学习的时候也会有这个感觉。不过,经过一段时间的学习之后,小编发现尽管函数有很多,但是常用的却只有那几个。今天小编就把常用的函数汇总一下,为大家能够能好的学习MySQL中的函数。MySQL常使用的函数大概有四类。时间函数、数学函数、字符函数、控制函数。让我...

  • 我们都知道,在.Net的鼠标事件中判断鼠标事件方法如下(以button为例): Private Sub Button1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Button1.Mou...

  • 情况一:后台给的日期是Sat Jul 31 2021 21:50:01 GMT+0800 (中国标准时间),如果直接呈现给用户,他们一定会吐槽你不说人话~~~ 情况二:后台给的百分数是小数没有转化成00%格式 采用vue的过滤机制就可以解决这种情况,有两种方式: 第一种:全局写法,在main.js里面加入 // 【...

  • 问题描述 使用main函数的参数,实现一个整数计算器,程序可以接受三个参数,第一个参数“-a”选项执行加法,“-s”选项执行减法,“-m”选项执行乘法,“-d”选项执行除法,后面两个参数为操作数。 例如:输入test.exe  -a 1 2       执行1+2输出3 问题分析 上面的逻辑思维很简单,但是问题在于如何在VS中向...

  • ------------------------siwuxie095                         MyBatis 中 #{} 和 ${} 的区别       1、在 MyBatis 的映射配置文件中,动态传递参数有两种方式:    (1)#{} 占位符    (2)${} 拼接符          2、#{} 和...

  •     #2.6 map()# 第一个参数传入一个函数,,第二个参数为一个可迭代对象li_1 = (1,3,5,7)def funcA(x): return x*xm1 = map(funcA,li_1)print(type(m1))print(m1())# 2.6 reduce()# 第一个参数传入一个函数,第二个参数 可以迭...

  • 列表,元组,字典的转换。 list列表是一组可变的元素集合 列表是'[]'括号组成的,[]括号包含所有元素,列表的创建可以传递字符串,也可以传递多个字符串来创建列表。如"asd", / "a","b" ... tuple元组的创建和列表一致,区别在于 元组是以'()'创建的,并且元组数据不可变。 dict字典不同于列表和元组,他...