Rocksolid Light

News from da outaworlds

mail  files  register  groups  login

Message-ID:  

BOFH excuse #366: ATM cell has no roaming feature turned on, notebooks can't connect


comp / comp.lang.scheme / Re: Homework question: LOOP

SubjectAuthor
* Re: Homework question: LOOPB. Pym
`- Re: Homework question: LOOPKaz Kylheku

1
Subject: Re: Homework question: LOOP
From: B. Pym
Newsgroups: comp.lang.lisp, comp.lang.scheme
Organization: A noiseless patient Spider
Date: Thu, 12 Sep 2024 10:12 UTC
Path: eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Nobody447095@here-nor-there.org (B. Pym)
Newsgroups: comp.lang.lisp,comp.lang.scheme
Subject: Re: Homework question: LOOP
Date: Thu, 12 Sep 2024 10:12:05 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 45
Message-ID: <vbuepk$6veu$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Injection-Date: Thu, 12 Sep 2024 12:12:06 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="0068c9cac97edf80ad7dcfbe07391a5a";
logging-data="228830"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/wnsLKBT1hmUwbX60o7rpA"
User-Agent: XanaNews/1.18.1.6
Cancel-Lock: sha1:iYqTXJ7cfarbQxOK2Nz9jt6uOW0=
View all headers

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))))

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 '()))
(if (equal? self (car lst))
(find test-fn seen)
(go (cdr lst) (cons (car lst) seen)))))

Subject: Re: Homework question: LOOP
From: Kaz Kylheku
Newsgroups: comp.lang.lisp, comp.lang.scheme
Organization: A noiseless patient Spider
Date: Thu, 12 Sep 2024 13:01 UTC
References: 1
Path: eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: 643-408-1753@kylheku.com (Kaz Kylheku)
Newsgroups: comp.lang.lisp,comp.lang.scheme
Subject: Re: Homework question: LOOP
Date: Thu, 12 Sep 2024 13:01:49 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 88
Message-ID: <20240912053206.469@kylheku.com>
References: <vbuepk$6veu$1@dont-email.me>
Injection-Date: Thu, 12 Sep 2024 15:01:49 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="fc240c90c706e031471363b92b2225a2";
logging-data="296458"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+KZsoBQcH8K5/+tdpEYbBQFii5vIjWMPo="
User-Agent: slrn/pre1.0.4-9 (Linux)
Cancel-Lock: sha1:pjKPyxQP2rTzY1hS1TLHL/w5+AY=
View all headers

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

1

rocksolid light 0.9.8
clearnet tor