Surprising behavior of dolist with break condition.

Q&A's, tips, howto's

Surprising behavior of dolist with break condition.

Postby TedWalther » Fri Apr 03, 2015 7:32 am

This affects dotimes, dolist, and the rest of the family.

I had a situation where I needed to scan through a list of numbers, and find the list index of the number that is just less than my target number.

Example:

Code: Select all
(set 'foo '(1 5 10 20 100 105))

(dotimes (i (+ -1 (length foo)) (> (foo i) 50)) (foo i))
=> true
;; was expecting return value of 20 (last value before triggering break condition)


With the break condition, the loop always returns true. This isn't what I expect; I expect the last value evaluated inside the form, not the condition test. I want to abort the loop as soon as I find the value I'm looking for. Is this wrong? It affects pretty much all the looping constructs, and was very surprising to me. Without the break condition, the loops return the last value evaluated in the body.

Also, is there a better idiom to do such scanning, some sort of binary search function?

I understand it is useful to know whether the break condition was triggered or not, couldn't that be saved in a system variable $brk the way regex output is? Also, even leaving $idx behind after a form evaluation would be nice too.
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence. Nine months later, they left with a baby named newLISP. The women of the ivory towers wept and wailed. "Abomination!" they cried.
TedWalther
 
Posts: 605
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC

Re: Surprising behavior of dolist with break condition.

Postby ralph.ronnquist » Fri Apr 03, 2015 9:19 am

Surprisingly often I also have that need of getting the index for the element prior to the match, and I've zeroed in on a phrase like the following:
Code: Select all
(let (i (find 50 foo >=)) (if (nil? i) (- (length foo) 1) (zero? i) nil (- i 1)))

In that way the looping is within the primitive, and it avoids indexing, which might be slow especially for longer lists.

Regarding the loop return value I think I would agree that it lacks coherence as is. However, as I use those forms only imperatively, that return value is outside my box.
ralph.ronnquist
 
Posts: 209
Joined: Mon Jun 02, 2014 1:40 am
Location: Melbourne, Australia

Re: Surprising behavior of dolist with break condition.

Postby newBert » Sat Apr 04, 2015 7:43 am

Here is another solution :

Code: Select all
(set 'foo '(1 5 10 20 100 105))
(last (ref-all 50 foo > true))   ;-> 20
BertrandnewLISP v.10.7.5 64-bit on Linux (Peppermint 9)
newBert
 
Posts: 138
Joined: Fri Oct 28, 2005 5:33 pm
Location: France

Re: Surprising behavior of dolist with break condition.

Postby TedWalther » Sun Apr 12, 2015 6:18 am

Ralph and NewBert, thank you for those answers. Ralph, that is amazing, I keep forgetting about the "find" function, that was beautifully done.

I ended up going with this before I read your solutions:

Code: Select all
(let (m 0) (while (> jday (lst m)) (++ m))))


In my application I didn't need a nil for no match, because I had a guarantee that the 0 index always pointed to a value that was less than the value I was testing.
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence. Nine months later, they left with a baby named newLISP. The women of the ivory towers wept and wailed. "Abomination!" they cried.
TedWalther
 
Posts: 605
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC


Return to newLISP in the real world

Who is online

Users browsing this forum: No registered users and 1 guest

cron