为何在Pact中调用纯函数的顺序会改变执行结果?
问题原因及解决方案
原因分析
你遇到的问题核心在于**select返回的是惰性求值的序列(游标),而非已固化的列表**:
- 在
sum-claims函数内部,两次fold操作都会遍历这个惰性序列; - 当在同一个函数调用上下文(比如
pretty-read-lock2/3的let*块)中连续调用两次sum-claims时,底层查询机制可能存在游标未重置、会话级结果累积的特性,导致第二次select重复读取了第一次的记录,最终累加出两倍的结果; - 单独调用
sum-claims时,函数执行完毕后上下文销毁,不会触发重复读取,因此结果正确。
从你的测试结果也能印证这点:不管先调用哪个sum-claims,第二个调用的结果都会是正确值的两倍。
解决方案
将select返回的惰性序列物化为具体的列表,确保每次查询的结果被固定下来,避免后续操作时重复读取。修改sum-claims中的records定义,用list函数包裹select的结果:
(defun sum-claims (lock-id:string coin-type:string) "Returns the total 'claimed' and 'coin-price' sums for the given lock-id and coin." (let* ( ; 把select结果转为列表,固化查询结果 (records (list (if (= "KDA" coin-type) (select claim-table (where "lock-number" (= lock-id))) (select external-claim-table (and? (where "lock-number" (= lock-id)) (where "coin-type" (= coin-type)))))) (total-claimed (fold (+) 0.0 (map (lambda (r) (at 'claimed r)) records))) (total-coin-price (fold (+) 0.0 (map (lambda (r) (at 'coin-price r)) records))) ) { "total-claimed": total-claimed , "coin-price": total-coin-price }) )
修改后,每次select的结果都会被转换成固定列表,无论是函数内部的两次fold,还是外部连续调用sum-claims,都会基于正确的单次查询结果计算,不会再出现数值翻倍的问题。
内容的提问来源于stack exchange,提问作者Nexion21
相关产品推荐
相关产品推荐

