Arc Forumnew | comments | leaders | submitlogin
1 point by greatness 5931 days ago | link | parent

A little prettier perhaps, though follows the same idea:

  (def range (st en (o step 1))
    (if (is step 0) (= step 1) (zap abs step))
    (let (stp-fn test) (if (> st en) `(,- ,<) `(,+ ,>))
       ((afn (i accum)
          (if (test i en) (rev accum)
                          (self (stp-fn i step) (push i accum))))
        st nil)))
If what order you want the range doesn't matter, you can remove the (rev accum) and replace it with accum. Example output:

  arc> (range 0 -5)
  (0 -1 -2 -3 -4 -5)
  arc> (range 5 5)
  (5)
  arc> (range 0 5)
  (0 1 2 3 4 5)
  arc> (range 0 10 2)
  (0 2 4 6 8 10)
  arc> (range 10 0 2)
  (10 8 6 4 2 0)
EDIT: added some error-checking, changing a step from 0 to 1 probably isn't the right thing to do, but I didn't feel like figuring out how to throw an error.


1 point by greatness 5931 days ago | link

Turns out consing up the list is faster, though without the rev function it is very close:

  (def range (st en (o step 1))
    (if (is step 0) (= step 1) (zap abs step))
      (let (stp-fn test) (if (> st en) `(,- ,<) `(,+ ,>))
        ((afn (i)
           (if (test i en) nil
                           (cons i (self (stp-fn i step)))))
         st)))
though I don't know why.

-----

1 point by joseph 5931 days ago | link

How about a default start of 0?

  (def range (default (o end) (o step 1))
    (with (st (if end default 0)
           en (if end end default))
      (if (is step 0) (= step 1) (zap abs step))
      (let (stp-fn test) (if (> st en) `(,- ,<) `(,+ ,>))
         ((afn (i accum)
            (if (test i en) (rev accum)
                            (self (stp-fn i step) (push i accum))))
          st nil))))

-----