函数中局部变量的值似乎没有在 Red/Rebol 语言中的函数调用后释放

问题描述

我构造了一个名为 find-all函数,以通过“递归”查找系列中给定项目的所有索引。 find-all 的第一次调用给出了正确的输出。然而,从第二次调用开始,所有输出都附加在一起。

find-all: function [series found][
result: [] 
  either any [empty? series none? s-found: find series found]
     [result]
     [append result index? s-found
      find-all next s-found found]
]

;; test:
probe find-all "abcbd" "b"   ;; output [2 4] as expected
probe find-all [1 2 3 2 1] 2  ;; output [2 4 2 4]

既然用function创建的函数内部的变量是局部变量,为什么后面函数调用的时候变量result的值还在,导致第二次调用result find-all 不以 [] 开头? 实现此功能的正确递归方法是什么?

解决方法

如果您在进行这两个调用后检查 find-all,答案很明显:

>> ?? find-all
find-all: func [series found /local result s-found][
    result: [2 4 2 4] 
    either any [empty? series none? s-found: find series found] 
    [result] 
    [append result index? s-found 
        find-all next s-found found
    ]
]

result 是一个 indirect value,它的数据缓冲区存储在一个堆上。数据在调用和累积之间得到保留和累积,因为您没有使用 copy 重新创建它 - result 是函数上下文的本地与此无关。

,

感谢@9214 的帮助,特别是关于indirect value 的描述。我给出了这样的解决方案:

find-all: function [series found][
  either any [empty? series none? s-found: find series found]
     [[]]
     [append
        reduce [index? s-found]
        find-all next s-found found
    ]
]

;; test:
probe find-all "abcbd" "b"   ;; output [2 4] as expected
probe find-all [1 2 3 2 1] 2  ;; output [2 4] as expected