在对用户自定义类型数组进行切片和拷贝之后,array.push() 会导致“下标越界”
在移除数组前缀时,我遇到了一个运行时错误。
我想要做的事:
我有一个检测器自定义类型(Detector UDT),它在一个数组中维护着Thing对象的历史。在某些情况下,我需要移除这个数组的前缀。我通过取一个表示该数组后缀的切片来实现,并用该切片的副本替换原数组。
问题:
在完成这次切片和拷贝操作后的下一根bar上,对新数组执行 array.push() 时,会抛出一个运行时错误:索引越界。有趣的是,只有在脚本执行流程后续的某个switch语句读取测试结果时,错误才会触发。移除switch语句后,错误就消失了。我无法解释这种交互。
重现:
//@version=6
indicator("Repro")
type Thing
int pos = -1
bool output = false
type Detector
array<Thing> things = na
method detect(Detector self, Thing t) =>
if na(self.things)
self.things := array.new<Thing>()
self.things.push(t)
prefix = self.things.slice(0, t.pos + 1)
if t.output
suffix = self.things.slice(t.pos + 1, self.things.size())
self.things := suffix.copy()
var Detector detector = Detector.new()
thing = switch bar_index
0 => Thing.new(pos=-1, output=false)
1 => Thing.new(pos=0, output=true)
2 => Thing.new(pos=0, output=true)
3 => Thing.new(pos=-1, output=false)
run_bar() =>
detector.detect(thing)
true
bool passed = true
passed := passed and run_bar()
result_colour = switch
passed => color.green
=> color.red
bgcolor(result_colour)
期望行为
push() 在Bar 3上的调用应当成功。
实际行为
脚本在Bar 3上失败,出现如下运行时错误:
Error on bar 3: In 'array.insert()' function. Index 2 is out of bounds, array size is 2.
at detect():17
at run_bar():33
at #main():37
感谢关注。希望我们能够为这个问题找到线索。
解决方案
问题的核心在于,你试图通过把 self.things 变量重新赋值为一个新的实例(suffix.copy())来“清理”数组。
在Pine Script中,当你使用 var Detector detector 时,对象会持续存在。然而,当你执行 self.things := suffix.copy() 时,你正在破坏Pine Script内部跟踪的原始数组引用。与 switch 语句相关的这种奇怪交互,是因为 switch 语句(以及其他流程控制结构)迫使编译器为变量的状态创建保存点。
如果编译器检测到数组的大小应基于上一次执行,但由于 copy() 导致引用发生变化,内部的插入指针就会失效。
以下是修正后的代码:
//@version=6
indicator("Reprp")
type Thing
int pos = -1
bool output = false
type Detector
array<Thing> things = na
method detect(Detector self, Thing t) =>
if na(self.things)
self.things := array.new<Thing>()
self.things.push(t)
if t.output
int items_to_remove = t.pos + 1
if items_to_remove > 0 and self.things.size() >= items_to_remove
for i = 1 to items_to_remove
self.things.shift()
var Detector detector = Detector.new()
thing = switch bar_index
0 => Thing.new(pos=-1, output=false)
1 => Thing.new(pos=0, output=true)
2 => Thing.new(pos=0, output=true)
3 => Thing.new(pos=-1, output=false)
=> na
run_bar() =>
if not na(thing)
detector.detect(thing)
true
bool passed = true
passed := passed and run_bar()
result_colour = switch
passed => color.green
=> color.red
bgcolor(result_colour)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。