Zulip Chat Archive
Stream: general
Topic: deep recursion in list.mmap
Eric Wieser (Jul 06 2022 at 09:03):
How am I supposed to write a for loop without hitting a deep recursion issue?
meta def main : io unit :=
do
(list.iota 10000).mmap $ λ i, do
{ io.put_str (format!"{i}\n").to_string },
pure ()
#eval main
gives
deep recursion was detected at 'formatter' (potential solution: increase stack space in your system)
Eric Wieser (Jul 06 2022 at 09:16):
This comment in doc-gen ran into the same issue:
Using
environment.mfold
is much cleaner. Unfortunately this led to a segfault, I think because
of a stack overflow. Converting the environment to a list of declarations and folding over that led
to "deep recursion detected". Instead, we split that list into 8 smaller lists and process them
one by one. More investigation is needed.
Eric Wieser (Jul 06 2022 at 09:49):
This seems to help:
/-- A version of `list.map` for `io` that does not consume the whole stack -/
def list.mmap_io {α β : Type*} (f : α → io β) (l : list α) : io (list β) :=
do
(_, bs) ← io.iterate (l, ([] : list β)) (λ state, do {
(a :: as, bs) ← pure state | return none,
b ← f a,
return (some (as, b :: bs))
}),
pure bs
Unfortunately I'm not allowed to @[vm_override]
that
Reid Barton (Jul 06 2022 at 12:15):
docs#list.mmap' works
Eric Wieser (Jul 06 2022 at 12:20):
Not for n = 100000 it doesn't
Reid Barton (Jul 06 2022 at 12:23):
I would not try to process that big a list then
Patrick Massot (Jul 06 2022 at 12:24):
Yes, this is a very well-known issue in Lean 3. I also hit it badly with LeanCrawler.
Eric Wieser (Jul 06 2022 at 13:17):
Is there a github issue or prior zulip thread that comes to mind?
Eric Wieser (Jul 06 2022 at 13:17):
Reid Barton said:
I would not try to process that big a list then
such long lists originate from docs#environment.get_decls
(the application here was exporting symbol information from a git repo to use as links in LaTeX)
Patrick Massot (Jul 06 2022 at 15:38):
Eric, there is probably related info in the thread https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/random.20io.20output
Mario Carneiro (Jul 10 2022 at 04:57):
Eric Wieser said:
Reid Barton said:
I would not try to process that big a list then
such long lists originate from docs#environment.get_decls
You should not use get_decls
if this is an issue. Instead use environment.fold
and just do what you need to do on each decl as it goes by without buffering them all into a list
Eric Wieser (Jul 10 2022 at 05:51):
Doesn't that hit the same problem if I fold over a monad? (I haven't tried)
Mario Carneiro (Jul 10 2022 at 05:58):
No; for example you can call trace
on all decls and nothing overflows. Building a list is also something you can do (this is how get_decls
works after all), it's just consuming the large list that causes a stack overflow
Eric Wieser (Jul 10 2022 at 06:27):
Wild, thanks for the tip
Eric Wieser (Jul 10 2022 at 06:27):
The list.mmap_io
definition above did also solve the problem though
Eric Wieser (Jul 10 2022 at 06:27):
But I guess only in one monad
Last updated: Dec 20 2023 at 11:08 UTC