命名函数
一个函数含有一组语句,调用该函数时,将执行该组语句。通常函数返回一个或多个值。在 DolphinDB 中,系统内置函数 不允许被改变定义。
内置函数与用户自定义函数均支持指定默认参数值。需要注意的是,默认值必须为常量,且可变参数( mutable 类型)不支持指定默认值。如果一个参数设置了默认值,后续参数都必须设置默认值。
New in version 1.30.13: 用户自定义函数的输入支持默认值
New in version 1.30.15: 用户自定义函数的输入支持 keyword
语法
def <functionName> ([parameters]) {statements}
或
def <functionName> ([parameters]): statement (can only have one statement here) (这里只能有一个语句)
我们将在本节末尾提及用户自定义聚合函数,其语法和命名函数基本一致,区别在于用户自定义聚合函数是以 defg 开头,而不是 def。
函数参数
函数参数通过引用传递。
当输入参数没有限定符时,在函数体中则不能修改该参数。
当参数用 mutable 修饰时,在函数体中可以修改该参数。
例子
定义一个命名函数:
$ def f(a){return a+1};
$ f(2);
3
$ def f(a):a+1;
$ f(3);
4
$ def f(a=1, b=2){return a + b}
$ f(,3)
4
将一个函数或者一组函数赋给变量:
$ g=sin;
$ g(3.1415926);
5.358979e-008
$ g=[sin, cos, log];
$ g(1 2);
sin |
cos |
log |
---|---|---|
0.841471 |
0.540302 |
0 |
0.909297 |
-0.416147 |
0.693147 |
//当一个函数和一个变量名字相同时,可以使用&来表示函数。
$ sum=15;
$ g=sum;
$ g;
15
$ g=∑
$ g;
sum
$ g(1..4);
10
不可变参数在函数体中不能被修改。
$ def f(a){a+=1; return a};
Syntax Error: [line #1] Constant variable [a] can't be modified.
可变参数在函数体中可以被修改。
$ def f(mutable a){a+=1; return a};
$ x=1;
$ f(x);
2
$ f(x);
3
$ x;
3
$ x=1..6$3:2;
$ x;
#0 |
#1 |
---|---|
1 |
4 |
2 |
5 |
3 |
6 |
$ def f(mutable a){if(a.rows()>=2 && a.cols()>=2){a[1,1]=0}; return a};
$ f(x);
#0 |
#1 |
---|---|
1 |
4 |
2 |
0 |
3 |
6 |
先声明函数再定义。
$ def f2(a,b)
$ def f1(a,b){return f2(a,b)}
$ def f2(a,b){a pow b};
// 这里在各行之间不应该添加";" ,否则系统会由于没有看到定义而无法识别出 f2 是一个声明。
$ f1(2,3);
8
多个返回值:
$ def summary(a){return sum(a), avg(a), std(a)};
$ x=1..11;
$ summary(x);
[66, 6, 3.316625]
更复杂的例子:
我们写一个函数,计算相同长度的向量之间的协方差。
(1) 如果 a 和 b 都不含有 NULL 元素,计算协方差。
(2) 如果 a 或 b 含有 NULL 元素,首先取得不含 NULL 元素的子向量,然后再计算协方差。
$ def calcovar(a, b){
$ aNull=hasNull a; // 如果输入向量含有 NULL 值,返回 true;否则返回 false
$ bNull=hasNull b;
$ if(!aNull && !bNull){ // 如果 a 和 b 都不含 null 值
$ am=avg a; // 使用 avg 函数计算向量 a 的均值
$ bm=avg b; // 使用 avg 函数计算向量 b 的均值
$ ab=a ** b; // 计算向量 a 和 b 的内积
$ n=count a; // 取得非 null 值数
$ return (ab-n*am*bm) \ (n-1); // 返回协方差
$ }
$ else{ // 取得 a, b 中所有不为 null 值的元素位置
$ if(!aNull) // 如果 a 不包含任何 null 值
$ index=!isNull b; // 取得所有 b 中非 null 值的下标
$ else {
$ if(!bNull) // 如果 b 不包含任何 null 值
$ index=!isNull a; // 取得所有 a 中非 null 值的下标
$ else
$ index=!((isNull a) || (isNull b)); // 取得所有 a 和 b 中同时为非 null 值的下标
$ }
$ c=a[index];
$ d=b[index];
$ am=avg c;
$ bm=avg d;
$ ab=c ** d;
$ n=count c;
$ return (ab-n*am*bm) \ (n-1);
$ }
$ }
用户自定义聚合函数
用户自定义聚合函数返回的数据格式为标量。有时候我们想确保一个函数返回的是一个标量,使用聚合函数就可以达到这个目的。
用户自定义聚合函数和命名函数语法基本一致,不同之处在于用户自定义聚合函数的定义以 “defg” 开头而不是 “def”。
$ defg f(x, y){
$ a = sum(abs(x+y))
$ b=sum(abs(x))+sum(abs(y))
$ return a\b
$ };
$ x=-5..5; y=0..10;
$ f(x,y);
0.858824