命名函数

一个函数含有一组语句,调用该函数时,将执行该组语句。通常函数返回一个或多个值。在DolphinDB中,系统内置函数 不允许被改变定义。

语法

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

将一个函数或者一组函数赋给变量:

$ 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=&sum;
$ 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