[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

I like LOOP

a.daniel.eliason

5/10/2016 7:47:00 PM

I wanted to scan consecutive pairs off a list. I almost had it:

(loop
for (a b) on '(1 2 3 4 5 6)
do (print `(,a ,b)))

But of course not what I wanted. I hashed it out:

(loop
for scanner = '(1 2 3 4 5 6) then (cddr scanner)
while scanner
for a = (car scanner)
for b = (cadr scanner)
do (print `(,a ,b)))

Perfect but what a mess. At least LOOP let me try it. Such a mess would never be the only way in LOOP. Certainly should be able to specify the stepping function. Yay! Much better:

(loop
for (a b) on '(1 2 3 4 5 6) by #'cddr
do (print `(,a ,b)))
13 Answers

Lieven Marchand

5/10/2016 7:52:00 PM

0

a.daniel.eliason@gmail.com writes:

> (loop
> for (a b) on '(1 2 3 4 5 6) by #'cddr
> do (print `(,a ,b)))

You can get replace `(,a ,b) by (list a b).

--
Although the invention of computer science has presented several inconveniences
to mankind - ask ordinary Iraqis what they think of the computers on a cruise
missile -, it offers a great advantage to mathematical pedagogy: a proof is
totally correct if a suitably programmed computer could understand it. Godement

a.daniel.eliason

5/10/2016 8:03:00 PM

0

On Tuesday, May 10, 2016 at 3:52:16 PM UTC-4, Lieven Marchand wrote:

> > (loop
> > for (a b) on '(1 2 3 4 5 6) by #'cddr
> > do (print `(,a ,b)))
>
> You can get replace `(,a ,b) by (list a b).


Except I prefer `(,a ,b) obviously.

Kaz Kylheku

5/10/2016 8:20:00 PM

0

On 2016-05-10, Lieven Marchand <mal@wyrd.be> wrote:
> a.daniel.eliason@gmail.com writes:
>
>> (loop
>> for (a b) on '(1 2 3 4 5 6) by #'cddr
>> do (print `(,a ,b)))
>
> You can get replace `(,a ,b) by (list a b).

Not just "you", but "your backquote expander".

Kaz Kylheku

5/10/2016 8:55:00 PM

0

On 2016-05-10, a.daniel.eliason@gmail.com <a.daniel.eliason@gmail.com> wrote:
> I wanted to scan consecutive pairs off a list. I almost had it:
>
> (loop
> for (a b) on '(1 2 3 4 5 6)
> do (print `(,a ,b)))
>
> But of course not what I wanted. I hashed it out:
>
> (loop
> for scanner = '(1 2 3 4 5 6) then (cddr scanner)
> while scanner
> for a = (car scanner)
> for b = (cadr scanner)
> do (print `(,a ,b)))
>
> Perfect but what a mess. At least LOOP let me try it. Such a mess
> would never be the only way in LOOP. Certainly should be able to
> specify the stepping function. Yay! Much better:
>
> (loop
> for (a b) on '(1 2 3 4 5 6) by #'cddr
> do (print `(,a ,b)))

WJ taking a day off today.

$ ./txr
This is the TXR Lisp interactive listener of TXR 140.
Use the :quit command or type Ctrl-D on empty line to exit.
1> [[callf (op mapcar list) identity cddr] '(1 2 3 4 5 6)]
((1 3) (2 4) (3 5) (4 6))
2> (tuples 2 '(1 2 3 4 5 6))
((1 2) (3 4) (5 6))

Notes:

(callf main-fun f0 f1 f2 ...) returns a function which applies
its arguments to each of the functions f0, f1, f2, .... From each of
these applications it retains the return value. These return values
then constitute the arguments in a call to main-fun, whose
value is ultimately returned.

Thus [callf (op mapcar list) identity cddr] gives us a
function which will pass its argument(s) to identity
and to cddr, and then do (mapcar list arg0 arg1) with these
two arguments. All we have to do is call it.

tuples is largely self-explanatory.

Here is another way:

3> (collect-each* ((a '(1 2 3 4 5 6))
(b (cddr a)))
(list a b))
((1 3) (2 4) (3 5) (4 6))

The noteworthy thing here is the treatment of a within the
binding sub-xpression of the collect-each* construct. Note
that we invoke (cddr a). What? Your eyes are not deceiving
you and there is no mistake. At that point in the code, the
variable a which is in scope is a list, as if the previous
(a '(1 2 3 4 5 6)) were a let binding. But then in the
body of the construct, these variables denote the elements
of those lists, iterated in parallel.

a.daniel.eliason

5/10/2016 9:22:00 PM

0

On Tuesday, May 10, 2016 at 4:55:06 PM UTC-4, Kaz Kylheku wrote:
> ...
> $ ./txr
> This is the TXR Lisp interactive listener of TXR 140.
> Use the :quit command or type Ctrl-D on empty line to exit.
> 1> [[callf (op mapcar list) identity cddr] '(1 2 3 4 5 6)]
> ((1 3) (2 4) (3 5) (4 6))
> 2> (tuples 2 '(1 2 3 4 5 6))
> ((1 2) (3 4) (5 6))
>
> Notes:
> ...
> tuples is largely self-explanatory.
> ...


(defun tuples (tuple-length tuples-source-list)
(loop
for scanner on tuples-source-list by (lambda (x) (nthcdr tuple-length x))
collect (subseq scanner 0 tuple-length)))


CL-USER> (tuples 2 '(1 2 3 4 5 6))
((1 2) (3 4) (5 6))
CL-USER>

Kaz Kylheku

5/10/2016 11:14:00 PM

0

On 2016-05-10, Daniel Eliason <a.daniel.eliason@gmail.com> wrote:
> On Tuesday, May 10, 2016 at 4:55:06 PM UTC-4, Kaz Kylheku wrote:
>> ...
>> $ ./txr
>> This is the TXR Lisp interactive listener of TXR 140.
>> Use the :quit command or type Ctrl-D on empty line to exit.
>> 1> [[callf (op mapcar list) identity cddr] '(1 2 3 4 5 6)]
>> ((1 3) (2 4) (3 5) (4 6))
>> 2> (tuples 2 '(1 2 3 4 5 6))
>> ((1 2) (3 4) (5 6))
>>
>> Notes:
>> ...
>> tuples is largely self-explanatory.
>> ...
>
>
> (defun tuples (tuple-length tuples-source-list)
> (loop
> for scanner on tuples-source-list by (lambda (x) (nthcdr tuple-length x))
> collect (subseq scanner 0 tuple-length)))
>
>
> CL-USER> (tuples 2 '(1 2 3 4 5 6))
> ((1 2) (3 4) (5 6))
> CL-USER>

More requirements:

Optional fill value for odd length.

1> (tuples 2 '(1 2 3))
((1 2) (3))
2> (tuples 2 '(1 2 3) :foo)
((1 2) (3 :foo))

Generic over vectors:

3> (tuples 2 #(1 2 3) :foo)
(#(1 2) #(3 :foo))

Strings:

4> (tuples 2 "abcde" :foo)
** cat-str: :foo is not a character or string
5> (tuples 2 "abcde" #\f)
("ab" "cd" "ef")
6> (tuples 2 "abcde")
("ab" "cd" "e")

Operate on infinite list without blowing up:

7> (take 12 (tuples 2 (range 1)))
((1 2) (3 4) (5 6) (7 8) (9 10) (11 12) (13 14) (15 16) (17 18)
(19 20) (21 22) (23 24))

Marco Antoniotti

5/11/2016 8:10:00 AM

0

WOW. What a subject line!

Troll fishing, aren't we? :) :) :)

MA






On Tuesday, May 10, 2016 at 9:47:18 PM UTC+2, Daniel Eliason wrote:
> I wanted to scan consecutive pairs off a list. I almost had it:
>
> (loop
> for (a b) on '(1 2 3 4 5 6)
> do (print `(,a ,b)))
>
> But of course not what I wanted. I hashed it out:
>
> (loop
> for scanner = '(1 2 3 4 5 6) then (cddr scanner)
> while scanner
> for a = (car scanner)
> for b = (cadr scanner)
> do (print `(,a ,b)))
>
> Perfect but what a mess. At least LOOP let me try it. Such a mess would never be the only way in LOOP. Certainly should be able to specify the stepping function. Yay! Much better:
>
> (loop
> for (a b) on '(1 2 3 4 5 6) by #'cddr
> do (print `(,a ,b)))

a.daniel.eliason

5/11/2016 12:30:00 PM

0

On Tuesday, May 10, 2016 at 7:13:39 PM UTC-4, Kaz Kylheku wrote:
> ...
> Operate on infinite list without blowing up:
>
> 7> (take 12 (tuples 2 (range 1)))
> ((1 2) (3 4) (5 6) (7 8) (9 10) (11 12) (13 14) (15 16) (17 18)
> (19 20) (21 22) (23 24))


What if you just did (tuples 2 (range 1))? Would you just get (1 2)? Or would it blow up?

Madhu

5/11/2016 12:38:00 PM

0


* Kaz Kylheku <20160510134343.427@kylheku.com> :
Wrote on Tue, 10 May 2016 20:55:00 +0000 (UTC):

| WJ taking a day off today.

^^^^^^^^^^^^^^^^^^^^^^^^^^^

| 3> (collect-each* ((a '(1 2 3 4 5 6))
| (b (cddr a)))
| (list a b))
| ((1 3) (2 4) (3 5) (4 6))
|
| The noteworthy thing here is the treatment of a within the
| binding sub-xpression of the collect-each* construct. Note
| that we invoke (cddr a). What? Your eyes are not deceiving
| you and there is no mistake. At that point in the code, the
| variable a which is in scope is a list, as if the previous
| (a '(1 2 3 4 5 6)) were a let binding. But then in the
| body of the construct, these variables denote the elements
| of those lists, iterated in parallel.

One valuble lesson from LOOP is that you can textually use loop
variables before you introduce their binding forms. Use of this loop
feature gives an important visual clue to the programmer: that the value
of the variable which is used textually is actually bound later: (say
after stepping). You could use this valuble lesson and make the macro
"less surprising" and less confusing to the programmer by letting him
write:

(collect-each* ((b (cddr a))
(a '(1 2 3 4 5 6)))
(list a b))

instead of

(collect-each* ((a '(1 2 3 4 5 6))
(b (cddr a)))
...)

OK. BTW callf is an `emacs cl' macro with what I consider "fairly
standard" semantics: roughly (?)

(defmacro callf (func place &rest args)
`(setf ,place (,func ,place ,@args)))

(defmacro callf2 (func arg place &rest args)
`(setf ,place (,func ,arg ,place ,@args)))

So nother callf macros is confusing. However I'm not sure what the
other callfs should be called ---Madhu

Kaz Kylheku

5/11/2016 1:09:00 PM

0

On 2016-05-11, Daniel Eliason <a.daniel.eliason@gmail.com> wrote:
> On Tuesday, May 10, 2016 at 7:13:39 PM UTC-4, Kaz Kylheku wrote:
>> ...
>> Operate on infinite list without blowing up:
>>
>> 7> (take 12 (tuples 2 (range 1)))
>> ((1 2) (3 4) (5 6) (7 8) (9 10) (11 12) (13 14) (15 16) (17 18)
>> (19 20) (21 22) (23 24))
>
>
> What if you just did (tuples 2 (range 1))? Would you just get (1 2)?
> Or would it blow up?

1> (tuples 2 (range 1))
((1 2) (3 4) (5 6) (7 8) (9 10) (11 12) (13 14) (15 16) (17 18)
[ ... hit Ctrl-C ...]
(305661 305662) (305663 305664) (305665 305666) (305667 305668)
** intr exception, args: ("intr")
2>

In all cases, tuples instantly returns a lazy list, which could be
infinite. The listener then wants to print it.

(Whether that can keep printing depends on whether something is
hanging on to a reference to thehead of that list, preventing it from
being GC'd. Of course, the bignums are getting bigger, so in any case,
eventually a bignum will have to be allocated which overwhelms the
allocator.)