• Re: SBCL complains where Lispwork does not: loop for i for j

    From B. Pym@Nobody447095@here-nor-there.org to comp.lang.lisp on Sun Aug 24 15:29:33 2025
    From Newsgroup: comp.lang.lisp

    B. Pym wrote:

    Jochen wrote:

    This ...

    CL-USER 1 > (loop for i for j in '(a b c) collect (cons i j))
    ((0 . A) (1 . B) (2 . C))

    works perfectly on LispWorks, but not with SBCL

    FOR is an unknown keyword in FOR or AS clause in LOOP.

    I found a way around it 'for i from 0' but am not sure if there is another smarter way to achieve this.

    I think the canonical way would be

    (loop for i upfrom 0
    for j in '(a b c)
    collect (cons i j))

    newLISP

    (map (curry list $idx) '(a b c))

    ((0 a) (1 b) (2 c))

    Gauche Scheme

    (let ((i (makeigen)) (col (makelbag)))
    (dolist (j '(a b c)) (col (cons (i) j)))
    (col))

    ((0 . a) (1 . b) (2 . c))

    Given:

    ;; Make an integer generator.
    (define (makeigen :optional (start 0) (step #f) (m #f))
    (let ((i start)
    (s step)
    (m m)) ;; mod
    (if m
    (lambda () (begin0 (mod i m) (inc! i s)))
    (if s
    (lambda () (begin0 i (inc! i s)))
    (lambda () (begin0 i (inc! i)))))))

    (define (makelbag :optional (raw #f) (pass-through #t))
    (let ((bag '()))
    (lambda args
    (if (null? args)
    (if raw bag (reverse bag))
    (if pass-through
    (begin0 (car args) (push! bag (car args)))
    (push! bag (car args)))))))
    --
    [T]he problem is that lispniks are as cultish as any other devout group and basically fall down frothing at the mouth if they see [heterodoxy].
    --- Kenny Tilton
    The good news is, it's not Lisp that sucks, but Common Lisp. --- Paul Graham --- Synchronet 3.21a-Linux NewsLink 1.2
  • From tpeplt@tpeplt@gmail.com to comp.lang.lisp on Sun Aug 24 14:53:01 2025
    From Newsgroup: comp.lang.lisp


    Jochen wrote:

    This ...

    CL-USER 1 > (loop for i for j in '(a b c) collect (cons i j))
    ((0 . A) (1 . B) (2 . C))

    works perfectly on LispWorks, but not with SBCL

    FOR is an unknown keyword in FOR or AS clause in LOOP.

    I found a way around it 'for i from 0' but am not sure if there is
    another smarter way to achieve this.

    I think the canonical way would be

    (loop for i upfrom 0
    for j in '(a b c)
    collect (cons i j))

    When variables iterate independently, they can be joined by
    rCy:andrCO or rCyandrCO in place of the subsequent rCyforrCO.

    For example, (colons added for emphasis):

    (loop
    :for i :upfrom 0 :and j :in '(a b c)
    :collect (cons i j))
    ((0 . A) (1 . B) (2 . C))

    Both control when the loop ends, so the first iterating
    expression can be the constraint on when to stop...

    (loop
    for i below 2 :and j in '(a b c)
    collect (cons i j))
    ((0 . A) (1 . B))

    ...or the second iterating expression can be the constraint
    on when to stop:

    (loop
    for i below 1000 :and j in '(a b c)
    collect (cons i j))
    ((0 . A) (1 . B) (2 . C))

    (loop
    for i downfrom 9 :and j in '(a b c)
    collect (cons i j))
    ((9 . A) (8 . B) (7 . C))

    See http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/sec_6-1-2-1.html

    "If multiple iteration clauses are used to control
    iteration, variable initialization and stepping[1] occur
    sequentially by default. The AND construct can be used to
    connect two or more iteration clauses when sequential
    binding and stepping[1] are not necessary. The iteration
    behavior of clauses joined by AND is analogous to the
    behavior of the macro DO with respect to DO*."
    --
    The lyf so short, the craft so long to lerne.
    - Geoffrey Chaucer, The Parliament of Birds.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From B. Pym@Nobody447095@here-nor-there.org to comp.lang.lisp on Sun Aug 24 22:02:51 2025
    From Newsgroup: comp.lang.lisp

    B. Pym wrote:

    Jochen wrote:

    This ...

    CL-USER 1 > (loop for i for j in '(a b c) collect (cons i j))
    ((0 . A) (1 . B) (2 . C))

    works perfectly on LispWorks, but not with SBCL

    FOR is an unknown keyword in FOR or AS clause in LOOP.

    I found a way around it 'for i from 0' but am not sure if there is another smarter way to achieve this.

    I think the canonical way would be

    (loop for i upfrom 0
    for j in '(a b c)
    collect (cons i j))

    Gauche Scheme

    "!" is somewhat like "do" except that it is optimized
    for brevity. So this is shorter than the "loop" solution.

    (! (r cons (cons i j)
    i 0 +
    j :in '(a b c))
    (not j) @)

    ((0 . a) (1 . b) (2 . c))

    Given:

    (define-syntax !-aux
    (syntax-rules (<> @ + - cons cdr :in :across :if ! )
    [(_ (:if bool z ...) ((v i u) seen ...) stuff ...)
    (!-aux (z ...)
    ((v i (if bool u v)) seen ...) stuff ...) ]
    [(_ (x :in lst z ...) seen (lets ...) stuff ...)
    (!-aux (x (and (pair? xs)(pop! xs)) <> z ...)
    seen
    (lets ... (xs lst)) stuff ...) ]
    [(_ (x :across vec z ...) seen (lets ...) stuff ...)
    (!-aux (x (and (< i (vector-length v))
    (begin0 (vector-ref v i) (inc! i))) <>
    z ...)
    seen (lets ... (v vec) (i 0)) stuff ...) ]
    [(_ (a b <> z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a b b)) stuff ...) ]
    [(_ (a b + z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a b (+ 1 a))) stuff ...) ]
    [(_ (a + n z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a 0 (+ n a))) stuff ...) ]
    [(_ (a b - z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a b (- a 1))) stuff ...) ]
    [(_ (a cons b z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a '() (cons b a))) stuff ...) ]
    [(_ (a b cdr z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a b (cdr a))) stuff ...) ]
    [(_ (a b c z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a b c)) stuff ...) ]
    [(_ (a b) (seen ...) stuff ...)
    (!-aux () (seen ... (a b)) stuff ...) ]
    [(_ (a) (seen ...) stuff ...)
    (!-aux () (seen ... (a '())) stuff ...) ]
    ;;
    [(_ () seen lets a b c ! action ...)
    (!-aux () seen lets (a b c) #t (action ...)) ]
    [(_ () seen lets a b ! action ...)
    (!-aux () seen lets (a b) #t (action ...)) ]
    [(_ () seen lets a ! action ...)
    (!-aux () seen lets a #t (action ...)) ]
    ;;
    [(_ () ((a b c) z ...) lets bool)
    (!-aux () ((a b c) z ...) lets bool a) ]
    [(_ () ((a b c) z ...) lets bool @)
    (!-aux () ((a b c) z ...) lets bool (reverse a)) ]
    [(_ () seen lets bool @ result stuff ...)
    (!-aux () seen lets bool (reverse result) stuff ...) ]
    [(_ () seen lets bool (what @ x z ...) stuff ...)
    (!-aux () seen lets bool (what (reverse x) z ...) stuff ...) ]
    [(_ () seen lets bool (what x ... @ z) stuff ...)
    (!-aux () seen lets bool (what x ... (reverse z)) stuff ...) ]
    [(_ () ((a b c) z ...) lets 0 stuff ...)
    (!-aux () ((a b c) z ...) lets (= 0 a) stuff ...) ]
    [(_ () seen lets bool result stuff ...)
    (let lets (do seen (bool result) stuff ...)) ]
    ))
    (define-syntax !
    (syntax-rules ()
    [(_ specs bool stuff ...)
    (!-aux specs () () bool stuff ...) ]
    ))
    --
    [T]he problem is that lispniks are as cultish as any other devout group and basically fall down frothing at the mouth if they see [heterodoxy].
    --- Kenny Tilton
    The good news is, it's not Lisp that sucks, but Common Lisp. --- Paul Graham --- Synchronet 3.21a-Linux NewsLink 1.2
  • From B. Pym@Nobody447095@here-nor-there.org to comp.lang.lisp on Wed Jun 18 22:47:57 2025
    From Newsgroup: comp.lang.lisp

    CL-USER 1 > (loop for i for j in '(a b c) collect (cons i j))
    ((0 . A) (1 . B) (2 . C))

    and, do you really like that code? is it readable?
    if I encounter such stuff, i'd yell "WTF??".

    I found a way around it 'for i from 0'

    as others have noted, canonic way is to use upfrom. for i upfrom 0.
    perfectly readable and makes sense for anybody, even if they do not know the language.

    Let's see if we can make it shorter by using a Lispy language
    instead of CL.

    Gauche Scheme

    (map cons (liota) '(a b c))
    ===>
    ((0 . a) (1 . b) (2 . c))
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From B. Pym@Nobody447095@here-nor-there.org to comp.lang.lisp on Fri Jun 27 13:28:05 2025
    From Newsgroup: comp.lang.lisp

    B. Pym wrote:

    Jochen wrote:

    This ...

    CL-USER 1 > (loop for i for j in '(a b c) collect (cons i j))
    ((0 . A) (1 . B) (2 . C))

    works perfectly on LispWorks, but not with SBCL

    FOR is an unknown keyword in FOR or AS clause in LOOP.

    I found a way around it 'for i from 0' but am not sure if there is another smarter way to achieve this.

    I think the canonical way would be

    (loop for i upfrom 0
    for j in '(a b c)
    collect (cons i j))

    newLISP

    (map (curry list $idx) '(a b c))

    ((0 a) (1 b) (2 c))

    Gauche Scheme

    gosh> (map cons (liota) '(a b c))
    ((0 . a) (1 . b) (2 . c))

    Paul Graham:

    I consider Loop one of the worst flaws in CL, and an example
    to be borne in mind by both macro writers and language designers.


    [In "ANSI Common Lisp", Graham makes the following comments:]

    The loop macro was originally designed to help inexperienced
    Lisp users write iterative code. Instead of writing Lisp code,
    you express your program in a form meant to resemble English,
    and this is then translated into Lisp. Unfortunately, loop is
    more like English than its designers ever intended: you can
    use it in simple cases without quite understanding how it
    works, but to understand it in the abstract is almost
    impossible.
    ....
    the ANSI standard does not really give a formal specification
    of its behavior.
    ....
    The first thing one notices about the loop macro is that it
    has syntax. A loop expression contains not subexpressions but
    clauses. The clauses are not delimited by parentheses;
    instead, each kind has a distinct syntax. In that, loop
    resembles traditional Algol-like languages. But the other
    distinctive feature of loop, which makes it as unlike Algol as
    Lisp, is that the order in which things happen is only
    loosely related to the order in which the clauses occur.
    ....
    For such reasons, the use of loop cannot be recommended.


    Dan Weinreb, one of the designers of Common Lisp:

    ... the problem with LOOP was that it turned out to be hard to
    predict what it would do, when you started using a lot of
    different facets of LOOP all together. This is a serious problem
    since the whole idea of LOOP was to let you use many facets
    together; if you're not doing that, LOOP is overkill.


    Barry Margolin:

    My recommendation is based on seeing many question in the past
    of the form "What happens if you use both XXX and YYY in the
    same LOOP?" The unfortunate fact is that when we were writing
    the standard we didn't have time to nail down all the possible
    interactions between different LOOP features, so many of these
    are not well specified. And even if we did get it right in
    the standard, it's likely to be difficult to find them and I
    wouldn't trust that all implementors got it right (many of
    those questions were probably from implementors, trying to
    figure out what they were supposed to do). And even if they
    all got it right, someone reading your code may not be able to
    figure it out.

    So, with all those potential problems, my feeling is that if
    you have to ask, it's probably better to use something other
    than LOOP.

    3. Loop is very powerful, granted, and many people are trying to
    argue that "you can do so much with loop that it's unreadable."
    This is not an argument.

    But it is! Because any use of LOOP has the potential to be
    unreadable, the reader must read it carefully to verify that
    it's just one of the cases that doesn't require careful
    reading!


    John Foderaro:

    I'm not trying to join a debate on loop. I just wanted to present
    the other side of [the issue so that] the intelligent people can
    then weigh the arguments on both sides.

    I'm not suggesting that loop can be fixed either by adding
    parenthesis or coming up with ways of indenting it to make it
    understandable. It's a lost cause.

    ...

    Another great example from kmp:

    === from kmp

    For example, you might think
    (loop with i = (random 100) for x from 1 to 10 do (print (list i x)))
    and
    (loop for i = (random 100) for x from 1 to 10 do (print (list i x)))
    meant the same in English, [but they don't do the same thing in loop]

    === end kmp

    loop lulls you into thinking that you understand the program since
    you understand English. Make no mistake about it, loop is its
    own language. If you use it you condem everyone who reads the
    code to also learn the loop language.
    --- Synchronet 3.21d-Linux NewsLink 1.2