前言
最近在玩肉丸工艺,AE网络中源质的自动化补充有点麻烦,不太想针对五十多种源质每种都做一个检测装置,所以用集成搞了这么一个玩意。
涉及到一些高阶函数的操作,会有一些数学推导。
本文中涉及到函数的地方会省略不必要的括号,例如
f(g(x), h(x)) = f (g x) (h x)
中缀表达式会被写成前缀表达式,与函数调用格式保持一致,例如
a + b = (+) a b
除此之外,要预先完成魔力水晶的自动化,这里补充源质是通过用源质冶炼厂处理对应的魔力水晶完成的。

整体思路
读取ae网络中的源质
找到数量不足的源质
输入对应的魔力水晶到源质冶炼厂
读取AE网络中的源质
由于这个版本的神秘能源,支持的功能比较有限,open computer也和神秘能源没有联动,因此只能使用集成的方块读取器来读取注魔供应器的nbt,从而获取网络中的源质信息。



可以看到,注魔供应器的nbt标签中,storedAspects为我们需要的网络源质信息,这里直接使用Integrated NBT中的NBT提取器来提取。(注:后续所有关于nbt的操作都使用这个模组来进行,不使用该模组也是可以的,但是处理nbt需要自行组合函数来完成)下图为提取出的sotredAspects字段。
该列表内容形如 [ {key:"ignis", amount: 42}, {key:"aqua", amount: 178}, {key:"metallum", amount: 147283}, ...... ]

找到数量不足的源质
简单来说,我们的目标是,把所有低于特定数量的源质名称,放到一个列表当中,例如[infernum, bestia...]
这里介绍一下几个集成提供的比较重要的函数
// 输入两个参数,函数 f 和一个列表,返回值是一个列表,列表中的元素为函数 f 作用到输入列表中的对应元素
map: map f [a, b, ...] = [f a, f b, ...]
// 输入两个参数,函数 f 和一个列表list,其中函数 f 是一个单参数函数,返回值为布尔类型
// 返回一个列表,该列表为list中所有满足函数 f 为真的元素
filter: filter f list = [ x | (x in list) and (f x) ]
// 输入两个函数 f 、g,返回一个新函数 h,其中 h x = g (f x)
pipe: pipe f g x = g (f x)
为了得到目标列表
用filter得到数量小于阈值的源质,这时列表形如 [ {key:"ignis", amount: 42}, {key:"aqua", amount: 178} ]
用map得到源质的名称,这时列表形如 [ "ignis", "aqua"]
所以我们需要针对上述两个步骤,分别构造作为输入参数的函数
针对过程2,较为容易实现,使用nbt提取器针对上述列表中的单个元素提取key字段即可(使用NBT提取器的操作符模式。注意不要对整个列表提取,应该首先用head函数或者get函数得到列表中的某个元素,然后针对该元素做nbt提取),得到的这个函数我们记作 to_map。
针对过程1,需要组合多个函数来实现,具体如下
记我们需要的函数为to_filter,则有
to_filter x
= (>) threshold (get_amount x)
= ((>) threshold) (get_amount x)
= pipe get_amount ((>) threshold)) x
= pipe get_amount (apply (>) threshold) x
因此得到 to_filter 的定义如下
to_filter = pipe get_amount (apply (>) threshold)
根据这个表达式构建函数 out 即可,其中 threshold 为可自定义的 Number 类型常量,即上文中提到的阈值。
由于函数(>)是一个二元函数,因此需要使用 apply 对其进行柯里化。
表达式中,get_amount 类似于上文中过程2,map 所使用的函数,但其提取的并不是源质的名称(key),而是源质的数量(amount)。
结合上述内容,我们得到了缺失的源质列表
aspect_names = map to_map ( filter to_filter ae_aspect_list)
输出源质对应的魔力水晶
先来看看魔力水晶的nbt长什么样子
可以看到,魔力水晶的nbt中含有源质的名称,因此我们需要构造一个函数,输入魔力水晶物品,输出该魔力水晶的源质是否在上文中的列表aspect_names中。
这个函数我们记作 is_output_item, 将 is_output_item 应用到物品输出口即可。
为了实现 is_output_item 函数,我们将该函数拆解成如下操作
根据物品获取nbt中的源质种类字符串
判断源质种类字符串是否在列表 aspect_names 中
针对过程1,我们可以使用内置的运算符 NBT() 完成(该运算符的名字里本身就带了一对括号,为了避免引起歧义,后续我们用NBT_item来称呼该函数),该运算符输入物品,输出该物品的nbt。
然后从nbt中提取出key字段(源质名称),使用nbt提取器来完成(同样记得使用操作符模式),从nbt提取器中得到的函数我们记作 get_aspect_name_from_nbt
过程1对应的函数记作get_aspect_name,则有
get_aspect_name x
= get_aspect_name_from_nbt (NBT_item x)
= pipe NBT_item get_aspect_name_from_nbt x
因此
get_aspect_name = pipe NBT_item get_aspect_name_from_nbt
针对过程2,集成动力提供了contains方法(列表包含,注意不要使用成了同名的字符串包含),第一参数为列表,第二参数为任意值,返回值为布尔类型,当列表中有与第二参数相同的元素时,返回true,否则返回false
因此有
is_output_item x
= contains aspect_names (get_aspect_name x)
= (contains aspect_names) (get_aspect_name x)
= pipe get_aspect_name (contains aspect_names) x
= pipe get_aspect_name (apply contains aspect_names) x
所以
is_output_item = pipe get_aspect_name (apply contains aspect_name)
源质燃烧与输入ae网络
如图所示,使用源质输入总线抽走源质,源动之焰从冶炼厂的底部输入。

其他注意事项
记得将集成的各个部件的运行间隔调大,否则对服务器的负担会比较大。物品输出口的工作间隔可以适当调短,保证源质冶炼厂始终工作即可。
另一种思路
另外一种解决方案是,先找到ae网络中源质数量最少的源质,然后输出对应的魔力水晶,如果读者有兴趣可以根据该方案来实现。
小提示:由于集成中没有提供排序相关的函数,找出最小值可采用“选择”“<”“reduce1”来实现。
后记
希望本教程中的关于高阶函数的运算对读者有帮助。如果对该教程有疑问、指出错误或者建议,欢迎在评论区回复。


