Zulip Chat Archive
Stream: lean4
Topic: Destructive Updates
Tomaz Gomes (Sep 15 2023 at 02:15):
Hi there! Is the following code linear? The comment above setD
says that the update is done destructively if the reference counter is one, but I am having some trouble to understand if this is the case here or not... thanks!
def invertPermutation : List Nat → MetaM (List Nat) := fun p => do
let size := p.length
let p: Array Nat := ⟨p⟩
let mut answer: Array Nat := ⟨List.replicate size 0⟩
for i in [ : size] do
answer := answer.setD (p.get! i) i
return answer.toList
Joachim Breitner (Sep 15 2023 at 06:16):
Based on my (so far preliminary) understanding of the system: yes, it should be!
Joachim Breitner (Sep 15 2023 at 06:20):
I wonder if there is a way to assert that inside the code, so that one wouldn't have to guess.
Maybe a throwIfNotExclusive
function?
Or a getStableName
and throwIfStableNamesDiffer
to check that answer
points to the same location in memory throughout.
@Sebastian Ullrich , have you had any thoughts in that directions?
Marc Huisinga (Sep 15 2023 at 07:06):
You can also use dbgTraceIfShared
for debugging:
def invertPermutation : List Nat → List Nat := fun p => Id.run do
let size := p.length
let p: Array Nat := ⟨p⟩
let mut answer: Array Nat := ⟨List.replicate size 0⟩
for i in [ : size] do
answer := dbgTraceIfShared "answer" answer
answer := answer.setD (p.get! i) i
return answer.toList
-- [0, 0, 1]
#eval invertPermutation [1, 2, 3]
def invertPermutation2 : List Nat → List Nat := fun p => Id.run do
let size := p.length
let p: Array Nat := ⟨p⟩
let mut answer: Array Nat := ⟨List.replicate size 0⟩
let sharedAnswer := answer
for i in [ : size] do
answer := dbgTraceIfShared "answer" answer
answer := answer.setD (p.get! i) i
return answer.toList ++ sharedAnswer.toList
-- shared RC answer
-- [0, 0, 1, 0, 0, 0]
#eval invertPermutation2 [1, 2, 3]
Last updated: Dec 20 2023 at 11:08 UTC