• (loop initially ... getting non-ANSI CL warning

    From Robert L.@21:1/5 to All on Tue Feb 15 12:04:09 2022
    * (Mirko.Vukovic @ gmail.com) Wrote on Wed, 23 Jan 2008 08:41:15 -0800 (PST): | Second, I was not clear in my original post, but Ken caught it: I am
    | parsing an ordered list.
    [...]
    | (defun collect-duplicates (list)
    | (loop
    | for a in list
    | for b in (cdr list)
    | when (equal a b)
    | collect b))
    |
    | It eliminates the (setf ...), and I must admit, the setf just did not
    | look right in the loop. But I could not think of another way of doing
    | it.

    Note that you can use LOOP destructuring like this:
    (loop for (a b) on list when (equal a b) collect b)

    To fix the duplicate elements in the returned list, you can use
    an extra loop variable like this.

    (defun collect-duplicates (list)
    "LIST is an ordered list without null elements."
    (loop for prev = NIL then a
    for (a b) on list
    when (equal a b) unless (equal prev a) collect a))

    (use srfi-1) ;; span for Gauche Scheme
    or
    (require srfi/1) ;; span for Racket
    (require srfi/26) ;; cut for Racket

    (define (dups xs)
    (if (null? xs)
    '()
    (let-values (((a b) (span (cut equal? <> (car xs)) xs)))
    (if (pair? (cdr a))
    (cons (car a) (dups b))
    (dups b)))))

    (dups '(a a a b c c c d d d d d))
    ===>
    (a c d)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert L.@21:1/5 to Robert L. on Tue Feb 15 12:28:12 2022
    On 2/15/2022, Robert L. wrote:

    * (Mirko.Vukovic @ gmail.com) Wrote on Wed, 23 Jan 2008 08:41:15 -0800 (PST):
    Second, I was not clear in my original post, but Ken caught it: I am
    parsing an ordered list.
    [...]
    (defun collect-duplicates (list)
    (loop
    for a in list
    for b in (cdr list)
    when (equal a b)
    collect b))

    It eliminates the (setf ...), and I must admit, the setf just did not
    look right in the loop. But I could not think of another way of doing
    it.

    Note that you can use LOOP destructuring like this:
    (loop for (a b) on list when (equal a b) collect b)

    To fix the duplicate elements in the returned list, you can use
    an extra loop variable like this.

    (defun collect-duplicates (list)
    "LIST is an ordered list without null elements."
    (loop for prev = NIL then a
    for (a b) on list
    when (equal a b) unless (equal prev a) collect a))

    (use srfi-1) ;; span for Gauche Scheme
    or
    (require srfi/1) ;; span for Racket
    (require srfi/26) ;; cut for Racket

    (define (dups xs)
    (if (null? xs)
    '()
    (let-values (((a b) (span (cut equal? <> (car xs)) xs)))
    (if (pair? (cdr a))
    (cons (car a) (dups b))
    (dups b)))))

    (dups '(a a a b c c c d d d d d))
    ===>
    (a c d)

    Gauche Scheme or Racket

    (require srfi/1) ;; delete-duplicates for Racket

    (define (dups xs)
    (delete-duplicates
    (filter-map (lambda (a b) (and (equal? a b) b)) xs (cdr xs))))

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From B. Pym@21:1/5 to Ken Tilton on Wed Aug 7 07:53:18 2024
    Ken Tilton wrote:

    [email protected] wrote:
    Hi,

    I am still in a bit of shock that my first loop attempt works, with
    one legalistic exception.

    This is my simple code to show duplicates in a list:

    (defun show-duplicates (list)
    (loop
    initially with ref = (first list)

    That is a blank initially clause. CLisp is being nice and coping with
    that and pretending you just wrote (loop with ref = (first list)....

    for entry in (rest list) do
    (if (equal ref entry)
    (print entry))

    Using when when when is suitable makes code more readable.

    (setf ref entry)))

    Loop is pretty powerful so you should have a nervous feeling when you
    find yourself setfing key iteration variables.

    It looks as if you are assuming a sorted list and simply printing out elements the same as the preceding element:

    (loop for (a b) on list
    when (eql a b)
    do (print b))

    You get an extra iteration on the last element and nil so an input list
    of '(nil nil) would print an extra duplicate. If that is a problem you can:

    (loop for a in list
    for b in (cdr list) ; this will run out first and halt the loop
    when (eql a b)
    do (print b))

    (setq list '(0 0 0 2 3 4 4 5 6 6 6))

    (loop for a in list
    for b in (cdr list) ; this will run out first and halt the loop
    when (eql a b)
    do (print b))

    0
    0
    4
    6
    6


    newLISP

    (setq lst '(0 0 0 2 3 4 4 5 6 6 6))

    (apply (fn (a b)(if (= a b) (println a)) b) lst 2)

    0
    0
    4
    6
    6

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)