Zulip Chat Archive
Stream: lean4
Topic: enumerate
Adam Topaz (Oct 05 2022 at 16:55):
What's the Lean4 idiomatic way to enumerate in a for loop (I'm thinking specifically of python's enumerate)?
The following feels too hacky!
#eval do
let a := #["a","b","c"]
for i in (List.range a.size).zip a.toList do
IO.println i
Gabriel Ebner (Oct 05 2022 at 17:00):
You can do
for h : i in [:a.size] do
have : i < a.size := h.2
IO.println (i, a[i])
or
for elem in a, i in [:a.size] do
IO.println (i, elem)
Jannis Limperg (Oct 05 2022 at 17:03):
What's the semantics of the second form if the two collections don't have the same size? Stop once the shorter one is exhausted?
Adam Topaz (Oct 05 2022 at 17:03):
Aha! I didn't know
for elem in a, i in [:a.size] do
IO.println (i, elem)
was possible!
Adam Topaz (Oct 05 2022 at 17:04):
#eval do
let a := #["a","b","c"]
for i in a, j in [:a.size + 2] do
IO.println (i, j)
stops at (c,2)
Adam Topaz (Oct 05 2022 at 17:06):
BTW, it seems that the two approaches that Gabriel mentioned cannot be combined!
#eval do
let a := #["a","b","c"]
for i in a, h : j in [:a.size] do
IO.println (i, j)
Adam Topaz (Oct 05 2022 at 17:07):
That gives an error at h.
Gabriel Ebner (Oct 05 2022 at 17:10):
You can do for h : j in [:a.size], elem in a do.
Andrés Goens (Oct 05 2022 at 21:01):
huh, that's a strange h you get there though, I would have expected it to be the same h that you need for a[i] there, as in something like:
#eval do
let a := #["a","b","c"]
for h : i in [:a.size] do
IO.println a[i]'h
Andrés Goens (Oct 05 2022 at 21:03):
but there seems to be a new col : Std.range being created and no relation to a.size
Andrés Goens (Oct 05 2022 at 21:03):
what's the use of that h : i ∈ col?
Mario Carneiro (Oct 05 2022 at 21:07):
I'm getting a weird parse error there BTW, expected ':' or ']' at the i in a[i]'h. It seems to be a precedence issue, IO.println (a[i]'h) works
Mario Carneiro (Oct 05 2022 at 21:08):
Note that col in this example is actually a let binding, if you wrap the term in by exact you can see the value of the binding
Gabriel Ebner (Oct 05 2022 at 21:09):
@Andrés Goens The h here has type 0 ≤ i ∧ i < a.size (because [:a.size] means [0:a.size]).
Mario Carneiro (Oct 05 2022 at 21:09):
(I'm not a big fan of this pretty printing trick of making let bindings look like regular bindings. Having := ... would be better)
Andrés Goens (Oct 05 2022 at 21:17):
Mario Carneiro said:
Note that
colin this example is actually a let binding, if you wrap the term inby exactyou can see the value of the binding
I'm not sure I follow, where would I wrap it in a by exact?
Mario Carneiro (Oct 05 2022 at 21:18):
like by exact IO.println (a[i]'h)
Andrés Goens (Oct 05 2022 at 21:18):
Gabriel Ebner said:
Andrés Goens The
hhere has type0 ≤ i ∧ i < a.size(because[:a.size]means[0:a.size]).
interesting, so this seems to work then from that type:
#eval do
let a := #["a","b","c"]
for h : i in [:a.size] do
IO.println (a[i]'(by exact h.2))
definitely not the most intuitive tbh :sweat_smile:
Mario Carneiro (Oct 05 2022 at 21:18):
the reason this makes a difference is that the tactic mode uses a different pretty printing setting that shows let binding values
Mario Carneiro (Oct 05 2022 at 21:20):
Yes, proofs and do blocks don't play well together ATM. It needs some design work but I don't think it is a high priority right now
Andrés Goens (Oct 05 2022 at 21:20):
Mario Carneiro said:
the reason this makes a difference is that the tactic mode uses a different pretty printing setting that shows let binding values
Ahh, I see, that's interesting!
Mario Carneiro (Oct 05 2022 at 21:21):
you don't actually need the by exact for it to typecheck
Mario Carneiro (Oct 05 2022 at 21:21):
just if you want to see that col is actually a let binding
Andrés Goens (Oct 05 2022 at 21:45):
I guess you still need to know the instance : Membership Nat Range to know what h actually means, or chase it down with a bunch of unfolds, like
unfold Membership.mem at h
unfold inferInstance at h
unfold Std.instMembershipNatRange at h
simp at h
or is there a more idiomatic way to do this?
Mario Carneiro (Oct 05 2022 at 21:47):
you can use conv at h => whnf if you wanted to see that it is an /\ of something
Andrés Goens (Oct 05 2022 at 21:57):
Mario Carneiro said:
you can use
conv at h => whnfif you wanted to see that it is an/\of something
huh, that's some pretty cool black magic there :nerd:
Andrés Goens (Oct 05 2022 at 21:58):
thx for that one!
Last updated: May 02 2025 at 03:31 UTC