Arc Forumnew | comments | leaders | submitlogin
3 points by thaddeus 5436 days ago | link | parent

I am not sure if it's a bug in arc that 'for' does not handle the reverse order or if it was never intended to work this way.

    arc> (for i 28 23
             (prn i))
    nil
http://arclanguage.org/item?id=9192

T.



3 points by pg 5428 days ago | link

It wasn't intended to, but I'd considering broadening the def. I'll look at the hn source to see how often I'd use this.

-----

1 point by thaddeus 5427 days ago | link

As a note - It may still be a good idea, but I care less after some thought:

Originally I was trying grab the last number of items in a table (something similar to your code in prompt.arc where you are grabbing/printing the last n items passed into the repl).

When using a list, as you had, we can easily grab the last 'n' items in the list since lists maintain order.

    (= records* (list "record 1 text" "record 2 text" "record 3 text" "record 4 text" "record 5 text" "record 6 text"))

    (def lastn (n nlist)
      (firstn n (rev nlist)))

    arc>(each record (lastn 3 records*)
      (prn record)) 

    record 6 text
    record 5 text
    record 4 text
However if storing the data in a table it's not as clear grabbing the last n items since tables have no inherent order. as you can see this isn't as straight forward:

    (= records* (obj 1 "record 1 text" 2 "record 2 text" 3 "record 3 text" 4 "record 4 text" 5 "record 5 text" 6 "record 6 text"))

    arc> (each record (firstn 3 (sort > (keys records*)))
         (prn (records* record)))

    record 6 text
    record 5 text
    record 4 text
so I had hoped 'for' in reverse would be cleaner...

    arc> (for i (len records*)(- (len records*) 3)
          (prn (records* i)))

    record 6 text
    record 5 text
    record 4 text
    record 3 text
only after re-writing I noticed that I was getting too many results thus ended up having to hack:

    arc> (for i (len records*)(- (len records*) 2) 0
          (prn (records* i)))
If my hope was to make the code more readable, it didn't work.

So.... instead I wrote 'grab':

    (def lastn (n nlist)
      (firstn n (rev nlist)))

    (def grab (which n them (o sop nil))
	 (case (type them)
	        table (case which first (if (no sop) (firstn n (sort < (keys them)))(firstn n (sort sop (keys them))))
	                          last  (if (no sop) (firstn n (sort > (keys them)))(firstn n (sort sop (keys them)))))
	        cons  (case which first (if (no sop) (firstn n them)(firstn n (sort sop them))) 
	                          last  (if (no sop) (lastn n them) (lastn n (sort sop them))))))
	
And now I feel it's much more readable + works on both lists and tables:

    arc>(each record (grab 'last 3 records*)
        (prn (records* record)))

    record 6 text
    record 5 text
    record 4 text
T.

[EDIT] - Hadn't thought about it until now, but it has re-use even if the table doesn't have nums for keys, it would also work on other keys (example grabbing the last n items of alphabetical order). Anyway... don't spend time on re-working 'for' it it doesn't help anyone else.....

-----