Clojure

Exceptions are not cached in lazy seqs

Details

  • Type: Enhancement Enhancement
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

It is confusing that exceptions will only be thrown once when it is possible to iterate over a seq many times.

user=> (def a (for [i (reverse (range 2))] (/ 1 i)))
#'user/a
user=> (println a)

ArithmeticException Divide by zero clojure.lang.Numbers.divide
(Numbers.java:156)
(user=> (println a)
(1)
nil
user=> (println a)
(1)
nil

Activity

Stuart Halloway made changes -
Field Original Value New Value
Priority Major [ 3 ] Minor [ 4 ]
Issue Type Defect [ 1 ] Enhancement [ 4 ]
Hide
Gary Fredericks added a comment -

The cause of this is the lazy-seq macro which uses :once metadata to signal to the compiler that the thunk it creates will only be called once.

When the evaluation of a lazy seq throws an exception, trying to walk the seq again causes the function to be called a second time. Since its closed over values have likely been cleared by that point, you get different behavior.

Glancing at LazySeq.java made me pretty convinced you can't cache exceptions without adding an extra check somewhere in the standard codepath for lazy seq traversal.

Show
Gary Fredericks added a comment - The cause of this is the lazy-seq macro which uses :once metadata to signal to the compiler that the thunk it creates will only be called once. When the evaluation of a lazy seq throws an exception, trying to walk the seq again causes the function to be called a second time. Since its closed over values have likely been cleared by that point, you get different behavior. Glancing at LazySeq.java made me pretty convinced you can't cache exceptions without adding an extra check somewhere in the standard codepath for lazy seq traversal.
Hide
Yongqian Li added a comment -

Btw, I ran into this issue while trying to evaluate a lazy-seq in a future in order to do some processing concurrently in the background. Any suggestions for workarounds?

Show
Yongqian Li added a comment - Btw, I ran into this issue while trying to evaluate a lazy-seq in a future in order to do some processing concurrently in the background. Any suggestions for workarounds?

People

Vote (1)
Watch (4)

Dates

  • Created:
    Updated: