如何无需命名位置参数,存储并排序函数混合参数后调用?
问题解决:Typst函数按数组参数排序调用且无需修改位置参数定义
问题背景
你定义了如下带位置参数(name)和命名参数的Typst函数:
#let monster( name, desc: "", strikes: 1, hits_on: 3, points: (), attacks: 1, doc: [] ) = { // 函数实现内容 }
你希望将多次调用该函数的参数存入数组,按name排序后批量调用函数,但现有实现需要为每个数组元素的位置参数name指定键名,且若使用..m展开操作还需将name设为可选——你不想给大量位置参数额外命名,也不想修改原函数的参数定义,询问如何实现需求。
你当前尝试的代码如下:
#let monsters = ( ( name: "Goblin", desc: "Small evil subserviant humanoid", doc: lorem(20), ), ( name: "Orc", doc: lorem(10), hits_on: 3, ), ( name: "Wight", desc: "Sentient flesh-eating undead", strikes: 3, points: ( [When taking a strike from a #monster, MR or be paralyzed for the scene.], [Loses a strike each turn spent exposed to sunlight.] ) ), ( name: "Zombie", strikes: 2, ), ( name: "Skeleton", ) ).sorted(key: m => m.name).map(m => monster(..m)).join()
解决方案
无需修改原函数的参数定义,也不用调整数组元素的写法,只需修改map中的函数调用逻辑:手动提取name作为位置参数传递,再展开移除name后的剩余键值对作为命名参数。
修改后的代码如下:
#let monsters = ( ( name: "Goblin", desc: "Small evil subserviant humanoid", doc: lorem(20), ), ( name: "Orc", doc: lorem(10), hits_on: 3, ), ( name: "Wight", desc: "Sentient flesh-eating undead", strikes: 3, points: ( [When taking a strike from a #monster, MR or be paralyzed for the scene.], [Loses a strike each turn spent exposed to sunlight.] ) ), ( name: "Zombie", strikes: 2, ), ( name: "Skeleton", ) ).sorted(key: m => m.name) .map(m => monster(m.name, ..m.without("name"))) .join()
原理说明
m.name直接提取数组元素中的name值,作为monster函数的第一个位置参数传递,符合原函数的参数要求。m.without("name")会生成一个移除了name键的新字典,再通过..展开操作将剩余键值对作为命名参数传递,避免了位置参数与展开的命名参数冲突。
这种方式既保留了你现有数组的写法,又不用修改原函数的参数结构,完美满足需求。
内容的提问来源于stack exchange,提问作者Matt Joiner
相关产品推荐
相关产品推荐

