Scribunto:入门/何时转换模板
在上一章中,我们了解到Scribunto是为了解决MediaWiki模板的性能问题而开发的。在Scribunto中,模板使用的大多数功能都是原生可用的,其他模板功能可以通过在Scribunto模块内部预处理原始模板代码来访问。换句话说,Scribunto可以做模板能做的一切。此外,Scribunto中的单个操作比模板代码中的操作更快。那么,是否应该将所有模板都转换为使用Scribunto而不是模板代码呢?
嗯,不完全是。
是否转换模板涉及多个因素,包括模板的复杂程度、它是否处理大量数据以及它包含哪些维基文本功能。评估转换模板的影响也是一个好主意,以确保您明智地花费编程时间。在本页中,我们将学习如何找到合适的模板进行转换,以及哪些模板应该保持原样。
首先,非常简单的模板不应该转换为Lua。主要由文本组成且不包含或几乎不包含解析器函数的模板应该保持原样。有两个原因。
第一个原因是运行Scribunto时存在轻微的开销。MediaWiki是用PHP编程语言编写的,Scribunto模块是用Lua编程语言编写的。从一种编程语言切换到另一种编程语言需要一些相当复杂的逻辑,这会占用处理时间。准备运行Lua模块的成本在2到4毫秒之间,具体取决于使用的Scribunto版本。一旦Lua初始化,Lua代码的运行速度会比等效的模板代码快得多,但初始开销意味着非常简单的模板运行速度会比等效的Lua模块快。
第二个原因是,简单的模板通常比等效的Lua模块更容易被编辑器阅读。虽然模板可能充满了条件逻辑和解析器函数,但它们最初的功能是在多个页面上显示相同或类似的内容。模板由于多年来积累的复杂性而获得了难以阅读的名声;但是,包含大量文本的简单模板很容易理解。另一方面,Lua模块具有专门的语法,适合表达复杂的逻辑。由于能够缩进代码和添加注释等,在Lua代码中而不是模板代码中表达复杂的逻辑通常更容易理解。但是,对于简单内容,使用模板是更易读的选择。
Scribunto模块比模板有一个很大的优势:您可以访问模板的所有参数。要使模板能够使用参数,必须在模板代码中显式指定该参数。例如,假设我们正在使用一个名为“模板:Hello”的模板,它向某人问好。它有以下代码
Hello, {{{name}}}!
如果我们使用代码{{hello|name=Anna}}
使用此模板,它将显示“Hello, Anna!”。这对于任何使用过MediaWiki模板的人来说可能都很熟悉。但如果我们使用代码{{hello|name=Anna|abc=def}}
调用它呢?
额外的参数不会对模板有任何影响;它只是显示“Hello, Anna!”。但是,在Lua模块中,我们可以检测到存在额外参数的事实,并根据它更改显示值。例如,我们可以显示一条错误消息,提示“检测到意外参数'abc'”。
这种能够看到传递给模板的所有参数的能力会产生一些有趣的影响。首先,这意味着Lua模块可以接受任意数量的参数。例如,考虑一个打印姓名列表的模板。它使用参数{{{1}}}
、{{{2}}}
、{{{3}}}
等作为姓名值。在模板代码中,您必须指定每个编号参数,如果您想要输出可变数量的参数,则必须测试每个参数是否存在。
List of names: {{{1}}}{{#if: {{{2|}}} | , {{{2}}} }}{{#if: {{{3|}}} | , {{{3}}} }} ...
这意味着模板可以输出的姓名数量始终有一个上限。如果您想输出20个姓名,模板代码中必须列出20个参数。但是,Lua没有这样的限制。您所要做的就是编写一些代码来为一个姓名构建一个列表项,然后将该代码用于传递给模板的每个姓名。如果传递了20个姓名给模板,您将使用该代码20次。如果只传递了三个姓名给模板,您将只使用该代码三次。如果传递了1000个姓名给模板,仍然不会有任何问题来显示它们。
能够获取传递给模板的所有参数是Lua比模板代码更快的最大原因之一。假设我们上面的示例模板被编写为最多输出10个姓名。
List of names: {{{1}}}{{#if: {{{2|}}} | , {{{2}}} }}{{#if: {{{3|}}} | , {{{3}}} }}{{#if: {{{4|}}} | , {{{4}}} }}{{#if: {{{5|}}} | , {{{5}}} }}{{#if: {{{6|}}} | , {{{6}}} }}{{#if: {{{7|}}} | , {{{7}}} }}{{#if: {{{8|}}} | , {{{8}}} }}{{#if: {{{9|}}} | , {{{9}}} }}{{#if: {{{10|}}} | , {{{10}}} }}
即使我们只需要一个包含三个姓名的列表,模板仍然检查所有10个参数以查看它们是否包含姓名。另一方面,Lua版本只会检查我们传递给它的三个姓名。检查参数需要相对较长的时间,因此Lua在类似此类应用中比模板代码具有很大的性能优势。
因此,具有{{{1}}}
、{{{2}}}
、{{{3}}}
等或{{{value1}}}
、{{{value2}}}
、{{{value3}}}
等参数的模板几乎总是应该转换为Lua。
某些模板旨在操作来自其他模板的参数。例如,英文维基百科上的模板:Unsubst与其他模板一起使用,以检查它们是否被错误地替换。如果被替换,模板:Unsubst将输出模板的未替换版本。模板:Unsubst要求模板作者手动输入其模板使用的所有参数;但是,在模块:Unsubst中转换为Lua之后,传递给模板的参数会自动检测。如果您想编写一个旨在处理传递给它的所有参数的模板,那么Lua是使用的工具。
另一个主要考虑转换为Lua的候选对象是复杂的模板。有时您会发现非常复杂的模板,它们包含许多解析器函数,并且调用也包含许多解析器函数的子模板,这些子模板又调用更多子模板……由于它们的层次结构很多,在Wikia上,这些模板被称为inceplates,源于电影《盗梦空间》。这些模板是受益于转换为Lua最多的模板。