Author Topic: Range Function  (Read 9929 times)

0 Members and 1 Guest are viewing this topic.

ymg

  • Guest
Range Function
« on: November 17, 2013, 12:51:33 AM »
Would there be any merit ?  to a range function like they have in Python.

Say we define the following:

Code - Auto/Visual Lisp: [Select]
  1. (defun in_range ( i j step / l)
  2.    (setq l (list i))
  3.    (while (< (setq i (+ i step)) j)
  4.       (setq l (cons i l))
  5.    )
  6.    (reverse l)
  7. )
  8.  

Now we could have construct like this and get away from updating the index:

Code - Auto/Visual Lisp: [Select]
  1. (foreach i (in_range 0 10 1)
  2.     ;;;
  3.    ;Do something here
  4. )
  5.  

ymg
« Last Edit: November 17, 2013, 01:52:27 AM by ymg »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Range Function
« Reply #1 on: November 17, 2013, 02:14:03 AM »
There are quite a few functions in Python and Javascript that would be handy in Lisp.


I recall that Tony T wrote a case() and let() function (similar to common lisp)  back in the day. I still use it regularly now.
« Last Edit: November 17, 2013, 03:11:31 AM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

ymg

  • Guest
Re: Range Function
« Reply #2 on: November 17, 2013, 02:19:49 AM »
Kerry,

Then maybe it would be worth to optimize it a little.

Too bad we don't really have the luxury of optional arguments.

Don't really know what is the speed impact as compared to incrementing an index.

ymg

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Range Function
« Reply #3 on: November 17, 2013, 03:10:36 AM »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

ymg

  • Guest
Re: Range Function
« Reply #4 on: November 17, 2013, 03:31:37 AM »
Kerry,

The let function is quite powerful.

Could use it I believe in that Levenberg-Marquardt solver.

Thanks, for sharing.

ymg

ymg

  • Guest
Re: Range Function
« Reply #5 on: November 17, 2013, 05:18:54 AM »
If we define in_range as follow, it would work both ways

Code - Auto/Visual Lisp: [Select]
  1. (defun in_range ( i j step / l)
  2.   (setq l (list i))
  3.   (repeat (- (fix (/ (- j i) step)) 1)    
  4.      (setq l (cons (setq i (+ i step)) l))
  5.   )
  6.   (reverse l)
  7. )
  8.  

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Range Function
« Reply #6 on: November 17, 2013, 05:48:40 AM »
Note:
Code: [Select]
(ymg_in_range_1 0 10.5 1) => (0 1 2 3 4 5 6 7 8 9 10)
(ymg_in_range_1 0 3 2) => (0 2)

(ymg_in_range_2 0 10.5 1) => (0 1 2 3 4 5 6 7 8 9)
(ymg_in_range_2 0 3 2) => (0)

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Range Function
« Reply #7 on: November 17, 2013, 06:03:16 AM »
For index ranges I have been using these two functions:

Code - Auto/Visual Lisp: [Select]
  1. ; Make a zero based list of integers.
  2. ; With speed improvement based on Reini Urban's (std-%setnth).
  3. ; (KGA_List_IndexSeqMakeLength 7) => (0 1 2 3 4 5 6)
  4. (defun KGA_List_IndexSeqMakeLength (len / ret)
  5.   (repeat (rem len 8)
  6.     (setq ret (cons (setq len (1- len)) ret))
  7.   )
  8.   (repeat (/ len 8)
  9.     (setq ret
  10.       (vl-list*
  11.         (- len 8)
  12.         (- len 7)
  13.         (- len 6)
  14.         (- len 5)
  15.         (- len 4)
  16.         (- len 3)
  17.         (- len 2)
  18.         (- len 1)
  19.         ret
  20.       )
  21.     )
  22.     (setq len (- len 8))
  23.   )
  24.   ret
  25. )
  26.  
  27. ; Make a list of integers from start index to end index.
  28. ; The Sequence always ends before the end index and the length of the result is: (abs (- end start)).
  29. ; This also applies if start is bigger than end. Input values can also be 'integers as reals'.
  30. ; With speed improvement based on Reini Urban's (std-%setnth).
  31. ; (KGA_List_IndexSeqMakeStartEnd 3 6) => (3 4 5)
  32. ; (KGA_List_IndexSeqMakeStartEnd 6 3) => (6 5 4)
  33. ; (KGA_List_IndexSeqMakeStartEnd -3.0 -8.0) => (-3.0 -4.0 -5.0 -6.0 -7.0)
  34. (defun KGA_List_IndexSeqMakeStartEnd (start end / len ret step)
  35.   (setq step (if (< start end) -1 1))
  36.   (repeat (rem (setq len (fix (abs (- end start)))) 8)
  37.     (setq ret (cons (setq end (+ end step)) ret))
  38.   )
  39.   (repeat (/ len 8)
  40.     (setq ret
  41.       (vl-list*
  42.         (+ end (* 8 step))
  43.         (+ end (* 7 step))
  44.         (+ end (* 6 step))
  45.         (+ end (* 5 step))
  46.         (+ end (* 4 step))
  47.         (+ end (* 3 step))
  48.         (+ end (* 2 step))
  49.         (+ end step)
  50.         ret
  51.       )
  52.     )
  53.     (setq end (+ end (* 8 step)))
  54.   )
  55.   ret
  56. )

ymg

  • Guest
Re: Range Function
« Reply #8 on: November 17, 2013, 06:34:55 AM »
roy_043,

Your function certainly work to give a range.

What I am really interested in is in using a construct of
the type python use,  for i in range(n):

and having something similar in Autolisp,  foreach i (in_range 0 n 1).

Would there be any advantage ?

Are we getting a hit speedwise ?

The in_range function as I gave it could certainly be optimized.

ymg

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Range Function
« Reply #9 on: November 17, 2013, 09:15:17 AM »
Using an index range can make the life of a Lisp programmer a little easier. But there are some speed concerns. I have tried to optimize my functions for speed by reducing the number of calls to (setq) and avoiding the use or (reverse). As mentioned this optimization is based on Reini Urban's (std-%setnth). But I have not compared the speed of functions that use a range to functions that do not. My guess is that using a range will generally be slower.

Below is an example of how I use (KGA_List_IndexSeqMakeLength):
Code - Auto/Visual Lisp: [Select]
  1. (setq pointList (KGA_List_Divide (vlax-get object 'coordinates) 2))
  2. (setq len (length pointList))
  3. (setq bulgeList
  4.   (mapcar
  5.     '(lambda (i)
  6.       (vlax-invoke object 'getbulge i)
  7.     )
  8.     (KGA_List_IndexSeqMakeLength len)
  9.   )
  10. )

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Range Function
« Reply #10 on: November 17, 2013, 09:18:10 AM »
Another offering:
Code - Auto/Visual Lisp: [Select]
  1. ;;  from start to end using step return the values
  2. ;;  integers only
  3. (defun in_range (start end step / value)
  4.   (setq value (list start))
  5.     (repeat (fix (/ (- end start) step))
  6.       (setq value (cons (setq start (+ step start)) value))
  7.     )
  8.   )
  9. )
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Range Function
« Reply #11 on: November 17, 2013, 09:34:35 AM »
@ CAB:
I am not sure but judging by ymg's first post all values in the return value should be smaller than the 'end' argument.
Code: [Select]
(cab_in_range_1 0 10 1) => (0 1 2 3 4 5 6 7 8 9 10)

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Range Function
« Reply #12 on: November 17, 2013, 09:37:29 AM »
@ ymg:
In the Python implementation is 'start' always smaller than 'end'?

ymg

  • Guest
Re: Range Function
« Reply #13 on: November 17, 2013, 11:40:49 AM »
Quote
In the Python implementation is 'start' always smaller than 'end'?

Not sure, I am actually quite Green in Python.

The whole idea would be to get rid of having to keep a separate index in for loop.

Mind you, it still would not be equivalent to a For... Next  as the range is compute beforehand
and you cannot modify it while the loop is running.

It does have the advantage of being quite readable.  But again would there be a hit on speed ?
We certainly are using more memory but this get freed eventually.

I like!!! Cab's offering, the only problem with it is that it includes end,
(in_range 0 5 1) should return (0 1 2 3 4), but is easy to fix.

ymg

Here from:    docs.python.org
Code - Python: [Select]
  1. range(start, stop[, step])
  2. This is a versatile function to create lists containing arithmetic progressions. It is most often used in for loops. The arguments must be plain integers. If the step argument is omitted, it defaults to 1. If the start argument is omitted, it defaults to 0. The full form returns a list of plain integers [start, start + step, start + 2 * step, ...]. If step is positive, the last element is the largest start + i * step less than stop; if step is negative, the last element is the smallest start + i * step greater than stop. step must not be zero (or else ValueError is raised). Example:
  3.  
  4. >>>
  5. >>> range(10)
  6. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  7. >>> range(1, 11)
  8. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  9. >>> range(0, 30, 5)
  10. [0, 5, 10, 15, 20, 25]
  11. >>> range(0, 10, 3)
  12. [0, 3, 6, 9]
  13. >>> range(0, -10, -1)
  14. [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
  15. >>> range(0)
  16. []
  17. >>> range(1, 0)
  18. []
  19.  
« Last Edit: November 17, 2013, 12:01:50 PM by ymg »

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Range Function
« Reply #14 on: November 17, 2013, 11:55:07 AM »
I posted something similar to Python's range function here - might be of interest.