Re: Homework question: LOOP

Liste des GroupesRevenir à cl scheme 
Sujet : Re: Homework question: LOOP
De : 643-408-1753 (at) *nospam* kylheku.com (Kaz Kylheku)
Groupes : comp.lang.lisp comp.lang.scheme
Date : 12. Sep 2024, 15:01:49
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <20240912053206.469@kylheku.com>
References : 1
User-Agent : slrn/pre1.0.4-9 (Linux)
On 2024-09-12, B. Pym <Nobody447095@here-nor-there.org> wrote:
Kenny Tilton wrote:
>
(defun prior-sib-if (self list &optional (test-fn #'true-that))
   "Find nearest preceding sibling passing TEST-FN"
   (labels ((check-priors (sibs)
              (if (eql self (first sibs))
                  nil
                (or (check-priors (rest sibs))
                  (when (funcall test-fn (first sibs))
                    (first sibs))))))
     (check-priors list)))
>
Peter Seibel wrote:
>
Ah, I missed that bit in the maze of twisty, recursive passages, all
alike. How about this bit of double loop delight:
 
  (defun prior-sib-if (self list &optional (test-fn #'true-that))
    "Find nearest preceding sibling passing TEST-FN"
    (loop with candidates = nil
        for node in list
        until (eql node self) do (push node candidates)
        finally (return (loop for c in candidates when (funcall test-fn c) retur
n c))))
>
Gauche Scheme
>
(use srfi-1) ;; take-while
>
(define (prior-sib-if self the-list test-fn)
  (find test-fn
    (reverse (take-while (^x (not (equal? self x))) the-list))))

There is no need to accumulate the candidates into a reverse
list which is then searched, like in Seibel's silly solution.

1. Iterate over the input.

   a. Stop when you see an item equal to the self object.

   b. Or else, whenever you see an item satisfying the predicate,
      remember it in the recent match variable.

2. If stopped via 1 (a), return the recent match variable, or else your
   not-found indication if nothing was assigned to that variable.
   (It could be that the variable is initialized to nil, and nil is the
   slightly ambiguous not-found indication.)

Why would you treat every preceding item as a "candidate", whether
it matches the predicate or not? If you only treated predicate-matching
elements as candidates, then the closest one would be (car candidates)
which would immediately inform you: why the heck am I keeping the whole
stack of them, only to end up peeking at the top element?

On top of that, you've ruined the elegance of using push to
get a reverse list.

gosh> (prior-sib-if 8 '(0 2 3 4 5 6 8 2 8) even?)
6
gosh> (prior-sib-if 8 '(0 2 3 4 5 6 8 2 8) odd?)
5
>
Another way:
>
(define (prior-sib-if self the-list test-fn)
  (let go ((lst the-list) (seen '()))
     ^^^^^^

It would behoove you to do.

    (if (equal? self (car lst))
      (find test-fn seen)
      (go (cdr lst) (cons (car lst) seen)))))

This is not equivalent. You're only calling (find test-fn seen)
when the self object has appeared in the list.

When the object does not appear in the list, you hit (car lst)
for an empty list, which blows up in Scheme.

The previous functions return the rightmost predicate-matching
element in the case when the self object has no appeared in the list.

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca

Date Sujet#  Auteur
12 Sep 24 * Re: Homework question: LOOP2B. Pym
12 Sep 24 `- Re: Homework question: LOOP1Kaz Kylheku

Haut de la page

Les messages affichés proviennent d'usenet.

NewsPortal