函数是 Quarkdown 的核心特性,正是它使 Quarkdown 有别于其他 Markdown 变体以及许多其他标记语言。函数从外部库中加载,这些库既可以是原生的(例如 标准库),也可以是在 Quarkdown 源文件中定义的,它们分为不同的类别:
| 类别 | 示例 |
|---|---|
| 布局规则 | row、column、grid、center |
| 实用视图 | tableofcontents、whitespace |
| 数学与逻辑运算 | sum、divide、pow、sin、isgreater |
| 控制结构与语句 | if、foreach、repeat、var、let、function |
| 文件数据 | include、csv、read |
| 文档元数据的修改 | docname、docauthor、doctype、theme、pageformat |
当从 Quarkdown 源文件中调用函数时,函数名前需加一个 .(点),每个参数都用花括号包裹。
.myfunction {arg1} {arg2}.multiply {6} {3}18
在前面的代码片段中,arg1 与 arg2 分别指代函数签名中的第一个与第二个参数。这些被称为位置参数,因为它们的含义由其在调用中的位置决定。
参数也可以按名称来指代某个参数。这些命名参数使用 name:{arg} 语法。
.myfunction firstparam:{arg1} secondparam:{arg2}你可以混合使用位置参数与命名参数,以提高函数调用的可读性,只要所有跟在命名参数之后的参数同样也是命名的即可。
.multiply {6} by:{3}18
参数可以跨越多行。缩进是可选且任意的。
.divide {
.cos {.pi}
} by:{
.sum {2} {1}
}-0.33333334
当一个函数调用包含许多参数时,行末的反斜杠(\)会将参数列表延续到下一行。
.container alignment:{center} \
background:{red} \
padding:{1px}反斜杠与换行符会被编译器消费掉,续接行开头可选的空白会被忽略。你可以根据需要用任意多个续接行。
行续接在块级与行内函数调用中均受支持。
函数调用可以嵌套在参数内部,从而让你组合出复杂的表达式。
.multiply {.pow {3} to:{2}} by:{.pi}28.274334
尽管 Quarkdown 完全依赖顶层声明,它还是利用了一些类 OOP 的语法糖,极大地提升了嵌套函数调用的可读性。
考虑下面这个调用:
.sum {.subtract {.pow {3} {2}} {1}} {2}它计算的是
.pow {3} {2}::subtract {1}::sum {2}好多了。现在它读起来就像我们自然地阅读数学的方式。
要理解链式调用的工作原理,考虑这个更简单的例子(请参阅变量 以了解更多关于变量的内容):
.myvar::uppercase在底层,编译器会将此调用转换为:
.uppercase {.myvar}.var {myvar} {hello!}
.myvar::uppercaseHELLO!
一般而言,.a::b 会被转换为 .b {.a},.a::b::c 转换为 .c {.b {.a}},依此类推。
你可以向链中的任意函数追加额外参数。只需记住:从位置上看,被链式的值始终是下一个调用的第一个参数。
.a {x}::b {y} 会被转换为 .b {.a {x}} {y}:
.sum {10} {5}::multiply {2}30
许多核心函数被设计成以链式方式调用,例如None 的操作。
一个函数调用通常必须被空白、符号,或一行的开头/结尾所包围。这意味着与单词字符直接相邻的一个调用不会被识别:
H.text {2} script:{sub}OH.text {2} script:{sub}O
将整个函数调用用花括号包裹,可以让它出现在任何位置,而不受周围字符的影响。包裹的花括号会被编译器消费掉,不会出现在输出中:
H{.text {2} script:{sub}}OH2O
函数调用可以出现在两种上下文中:行内或块级。
一个行内函数调用,其前后带有其他行内内容,例如文本。行内函数调用的输出会被简单地替换到父块中。
Ever wondered what **26+16** equals? It's .sum {26} {16}. Here you go.Ever wondered what 26+16 equals? It’s 42. Here you go.
一个块级函数调用是孤立的。作为背景,在 Markdown 中,块是指一个段落、一段代码片段、一段引用、一个列表,等等。
Paragraph 1
.myfunction {arg1} {arg2}
Paragraph 2函数最多接受一个主体参数,它指向函数的主体参数:通常是签名中的最后一个参数,不过有些函数会将另一个参数指定为主体(在其文档中以Likely body 显示)。
主体参数跨越多行,不使用括号包裹,并且要求每一行都缩进至少两个空格或一个制表符:
.myfunction {arg1} {arg2}
Body argument, line 1
and line 2.整个主体必须共享相同的缩进。下面这个例子由于缩进不一致,会产生意外结果:
.myfunction {arg1} {arg2}
Body argument, line 1
and line 2. <!-- 这是一个 4 空格缩进的代码块! -->其他函数,无论是块级还是行内,都可以嵌套在主体参数内部:
.row alignment:{center} <!-- 块级 -->
This document was made by .docauthor <!-- 行内 -->
.column <!-- 块级 -->
The document name is .docname <!-- 行内 -->
.loremipsum <!-- 块级 -->