仅含1个Token的Box无法通过跳过Token检查的if-else分支如何处理
问题根因
ErgoScript 会在编译阶段对所有集合的硬索引访问做静态越界校验,不会因为你在if条件里写了长度判断,就自动跳过else分支里的索引越界检查。
哪怕你逻辑上能保证走到else分支时SELF.tokens长度一定≥2,只要代码里出现SELF.tokens(1)这种直接按固定索引取值的写法,编译器就会要求在编译阶段就能确认索引合法。当Box只有1个Token时,编译器判定索引1越界,就会直接报编译错误,不会等到运行时再走分支判断。
可行解决方案
方案1:使用getOrElse安全取值(最简洁推荐)
放弃直接硬索引取值,改用集合自带的getOrElse方法,给索引位置传入一个永远不会触发逻辑判断的默认值,既不影响原有逻辑,也能通过编译器的静态检查:
val checkTokens: Boolean = if (SELF.tokens.size < 2) true else { // 第二个参数是兜底默认值,实际走到else分支时长度≥2,默认值不会被用到 val secondToken = SELF.tokens.getOrElse(1, (Coll[Byte](), 0L)) secondToken._1 == _tokenId.get && secondToken._2 < x }
方案2:用集合模式匹配(多Token判断场景更清晰)
通过模式匹配直接按结构解构Token集合,编译器会自动根据匹配的集合长度判定索引合法性,不会触发越界报错:
val checkTokens: Boolean = SELF.tokens match { case Coll(_) => true // 匹配仅含1个Token的场景,直接返回true case Coll(_, secondToken, _*) => // 匹配2个及以上Token的场景 secondToken._1 == _tokenId.get && secondToken._2 < x }
方案3:先切片再访问(兼容老版本场景)
如果当前使用的ErgoScript版本不支持前两种写法,可以先把集合切片到目标长度,再做索引访问,也能通过编译检查:
val checkTokens: Boolean = { val fixedLenTokens = SELF.tokens.slice(0, 2) if (fixedLenTokens.size < 2) true else { fixedLenTokens(1)._1 == _tokenId.get && fixedLenTokens(1)._2 < x } }
内容的提问来源于stack exchange,提问作者kii
相关产品推荐
相关产品推荐

