Hacker News new | past | comments | ask | show | jobs | submit login

I know there are much earlier examples, but the earliest warning about this behavior I could find in 60 seconds of searching is from the comp.lang.lisp FAQ, posted more than 30 years ago, in 1992:

    Mar 21, 1992, 1:00:47 AM
    Last-Modified: Tue Feb 25 17:34:30 1992 by Mark Kantrowitz
    ;;; ****************************************************************
    ;;; Answers to Frequently Asked Questions about Lisp ***************
    ;;; ****************************************************************
    ;;; Written by Mark Kantrowitz and Barry Margolin
    ;;; lisp-faq-3.text -- 16886 bytes
    
    [...]

    ----------------------------------------------------------------
    [3-9] Closures don't seem to work properly when referring to the
    iteration variable in DOLIST, DOTIMES and DO.
    
    DOTIMES, DOLIST, and DO all use assignment instead of binding to
    update the value of the iteration variables. So something like
    
    (dotimes (n 10)
      (push #'(lambda () (incf n))
            *counters*))
    
    will produce 10 closures over the same value of the variable N.
    ----------------------------------------------------------------



D too https://issues.dlang.org/show_bug.cgi?id=2043.

That's actually expected when capturing by reference.


In the standard it is not specified if such loops mutate or rebind, and you have to assume it doesn't rebind if you capture variables. I do think however that once you learn how it works it stops being a problem (in any case I can select the form, macroexpand it and it shows how it's implemented)


In theory sure. In practice it's easy enough to make this mistake mindlessly. I had this happen to me after many years of practice just this year (in an elaborate extended LOOP form which has same semantics).




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: