自定义函数
如果你一次又一次地输入同一个公式、只是换了数字,就把它变成函数吧。只需给公式和它的输入命名一次,之后在任何需要结果的地方调用它即可:小费计算器、BMI 检测、储蓄预测或发票都可以这样做。
本页介绍如何定义和调用函数、函数如何使用笔记中的其他名称、条件与递归,以及适用的限制。Varlig 自带的函数(如 sqrt 和 round)请参阅内置函数参考。
定义和调用函数
依次写出函数名、括号中的参数、等号和公式。然后按相同的顺序传入值来调用它:
小费(账单, 比例) = 账单 * 比例小费($48, 15%) 结果为 $7.20小费($120, 12.5%) 结果为 $15.00小费($36 + $12, 15%) 结果为 $7.20定义行不显示结果。每次调用都会用你传入的值替换 账单 和 比例,然后计算公式。参数可以是一整个计算式,如上面的 $36 + $12。
参数是完整的值,而不只是数字,所以单位和货币会贯穿整个公式:
bmi(体重, 身高) = 体重 / 身高^2bmi(81 kg, 1.8 m) 结果为 25 kg/m²单位会按你给出的样子保留,所以 bmi(81 kg, 180 cm) 的结果以 kg/cm² 表示。要让结果无论传入什么都使用同一单位,请在函数内部换算:
bmi(体重, 身高) = (体重 / 身高^2) in kg/m^2bmi(81 kg, 180 cm) 结果为 25 kg/m²bmi(80 kg, 5.9 ft) 结果为 24.7375131668 kg/m²函数也可以没有参数。定义和调用时都要写上空括号:
标准税率() = 20%£120 * 标准税率() 结果为 £24.00普通变量(如 标准税率 = 20%)通常也能完成同样的工作,而且输入更少。
名称与参数
- 函数名和参数名都是单个词。可以使用字母、数字和下划线,如
税后_月薪或bmi2,不能有空格。如果你写成圆 面积(r) = pi * r^2,这一行会建议你改用名称圆_面积。 - 函数名不区分大小写:定义
BMI(体重, 身高)后,可以调用bmi(81 kg, 1.8 m)。 - 每个参数都需要有自己的名称。
f(a, a) = a会报错。 - 一个函数最多可以有 32 个参数。
- 不能重复使用内置函数的名称。
round(x) = …或sqrt(x) = …会显示错误,而不会替换内置函数。普通变量仍然可以使用这些名称,如floor = 12 m²;请参阅名称。 - 电子表格中的写法
avg、total和stdev可以随意使用。自己定义一个total(订单),运行的就是你的版本。 - 函数和变量可以同名。
费率读取变量,费率(5)则调用函数。 - 调用函数时务必加上括号。如果单独写函数名,又没有同名变量,会显示错误。
参数中的逗号
逗号后面跟空格时用于分隔参数,逗号后面紧跟三位数字时则用于千位分组,所以你可以按平常的习惯书写金额:
小费(账单, 比例) = 账单 * 比例小费($1,200, 15%) 结果为 $180.00小费($1200,15%) 结果为 $180.00如果函数需要的值比按空格分出的值更多,每个逗号都会用于分隔,就像第二次调用那样。小数请使用小数点,如 小费($48, 12.5%)。
使用笔记中的其他名称
函数可以使用笔记中的变量。每次调用时,它都会读取变量的当前值:
增值税 = 20%含税价(价格) = 价格 * (1 + 增值税)含税价(£50) 结果为 £60.00增值税 = 5%含税价(£50) 结果为 £52.50定义函数时变量必须已经存在,所以请把 增值税 = 20% 放在 含税价 上方。如果变量尚不存在,定义行会显示错误。
参数只在函数内部有效。名为 价格 的参数不会读取或更改笔记中其他地方名为 价格 的变量:
价格 = £10加倍(价格) = 价格 * 2加倍(£3) 结果为 £6.00价格 结果为 £10.00与变量一样,在一个计算块中定义的函数,可以在同一条笔记后面的计算块中使用。Varlig 会从上到下处理笔记,所以请把函数定义在第一次调用它的行上方。位于定义上方的调用不会显示结果。
调用其他函数的函数
小函数可以层层组合:
日费率 = £400费用(天数) = 天数 * 日费率发票(天数) = 费用(天数) * 1.2发票(5) 结果为 £2,400.00函数会记住定义它时已存在的辅助函数版本。如果你在下面再次定义同一个辅助函数,之前定义的函数仍然使用旧版本:
运费(订单) = £4.95总额(订单) = 订单 + 运费(订单)运费(订单) = £2.95总额(£30) 结果为 £34.95运费(£30) 结果为 £2.95要使用新的 运费,请在它下方重新定义 总额。直接修改原有定义则不会出现这种情况。Varlig 会从顶部重新计算笔记,所以下方的所有内容都会使用你修改后的版本。
函数也可以调用在它下方定义的辅助函数。这时它使用的是调用时该辅助函数的版本,所以在调用外层函数之前,辅助函数必须已经存在:
结账(订单) = 订单 + 配送费(订单)配送费(订单) = if 订单 >= £40 then £0 else £3.50结账(£25) 结果为 £28.50结账(£60) 结果为 £60.00条件
使用 if … then … else … 在不同结果之间选择。如果情况多于两种,可以在 else 后面再接一个 if:
邮费(重量) = if 重量 <= 100 g then £0.85 else if 重量 <= 750 g then £1.55 else £3.20邮费(90 g) 结果为 £0.85邮费(500 g) 结果为 £1.55邮费(1.2 kg) 结果为 £3.20只有适用的那个分支会被计算。这样就能防止原本会失败的计算,比如除以零:
人均(总额, 人数) = if 人数 > 0 then 总额 / 人数 else £0人均(£90, 3) 结果为 £30.00人均(£90, 0) 结果为 £0.00递归
函数可以调用自身,只要某个条件最终能让它停下来。下面这个函数计算一群人两两握手一次的总次数:
握手次数(人数) = if 人数 <= 1 then 0 else (人数 - 1) + 握手次数(人数 - 1)握手次数(6) 结果为 15握手次数(10) 结果为 45每次调用都会再嵌套一层,最多允许 16 层嵌套调用。握手次数(16) 仍然有效,但 握手次数(17) 会显示 Error: calculation limit。永远到不了终止条件的函数在定义时会被接受,调用时则会触及同样的限制。两个函数也可以互相调用,同样受此限制。
日常计数使用内置函数更快,而且没有这种限制。combination(10, 2) 同样得到 45,而 factorial(n) 或 n! 则涵盖了经典的递归示例。
列表、矩阵及其他
参数可以是列表、矩阵或复数,函数体可以使用任何内置函数:
极差(成绩) = max(成绩) - min(成绩)极差([12, 18, 9, 21]) 结果为 12函数体中也可以包含带有自己局部变量的求和或方程求解。请参阅列表与统计和求和、解方程与微积分。
常见陷阱
- 用
^书写幂。 函数中不接受x²。更麻烦的是,较短的参数名可能与单位同名:在w / h²中,h²表示平方小时,而不是参数h。请写w / h^2。 - 检查参数个数。 函数需要两个值时调用
小费($48)会显示错误。 - 一行一个公式。 定义是写在一行中的单个表达式。对于有多个步骤的计算,请为每一步定义一个小函数,再把它们组合起来。
- 有误的重新定义会保留旧版本。 如果
小费的新定义有错误,该行会显示错误,之前可用的小费仍然可以使用。 - 笔记重新计算时结果可能改变。 每次都会重新计算调用,所以使用
random或今天日期的函数可能会给出新的结果。 - 错误会传递出来。 如果某个参数导致公式失败(比如除以零),调用就会显示该错误。
限制
| 项目 | 限制 |
|---|---|
| 每个函数的参数个数 | 32 |
| 嵌套调用(函数调用自身或其他函数) | 16 |
| 计算一次顶层调用期间发生的调用次数 | 16,384 |
| 一条笔记中定义的函数个数 | 1,024 |
触及限制时会显示 Error: calculation limit。笔记的其余部分仍会正常工作。所有限制请参阅错误、诊断与限制。
综合运用
下面是一份自由职业发票。日费率和增值税作为命名值放在顶部,由三个小函数完成计算:
# 三月发票日费率 = CNY 3000增值税 = 6%费用(天数) = 天数 * 日费率含税价(金额) = 金额 * (1 + 增值税)滞纳金(金额, 逾期天数) = if 逾期天数 > 30 then 金额 * 2% else CNY 0设计 = 费用(8) 结果为 24,000.00 CNY开发 = 费用(4.5) 结果为 13,500.00 CNY小计 = 设计 + 开发 结果为 37,500.00 CNY含税价(小计) 结果为 39,750.00 CNY滞纳金(含税价(小计), 45) 结果为 795.00 CNY修改 日费率 或 增值税,下面的每一行都会随之更新。如果客户逾期付款,一次调用就能加上滞纳金。