Posted By

timm on 02/25/12


Tagged

looping


Versions (?)

LUA's for loops (in LISP)


 / Published in: Lisp
 

The LUA programming language supports iterators.

The LUA for loop takes some generate function and asks it to produce a function that can return the next item.

A loop is then entered. The next item is generated. If it is non-nil, then the body of the loop is called to consume that item.

Otherwise, it exit.

The following LISP macro emulates that for command.

  1. (defmacro for ((item producer) &body consume)
  2. (let ((step (gensym "STEP"))
  3. (next (gensym "NEXT"))
  4. (run (gensym "RUN")))
  5. `(let ((,step ,producer))
  6. (labels ((,next () (funcall ,step))
  7. (,run (,item)
  8. (when ,item
  9. ,@consume
  10. (,run (,next)))))
  11. (,run (,next))))))
  12.  
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14. ; EXAMPLE 1: generate a bunch of odd numbers
  15.  
  16. (defun odds(max)
  17. (let ((i 0))
  18. #'(lambda ()
  19. (incf i)
  20. (if (evenp i)
  21. (incf i))
  22. (if (<= i max)
  23. i))))
  24.  
  25. (defun !for1 ()
  26. (for (item (odds 10))
  27. (print item)))
  28.  
  29. #|
  30. (LET ((#:STEP1404 (ODDS 10)))
  31. (LABELS ((#:NEXT1405 ()
  32. (FUNCALL #:STEP1404))
  33. (#:RUN1406 (ITEM)
  34. (WHEN ITEM (PRINT ITEM) (#:RUN1406 (#:NEXT1405)))))
  35. (#:RUN1406 (#:NEXT1405))))
  36.  
  37. CL-USER> (!for1)
  38.  
  39. 1
  40. 3
  41. 5
  42. 7
  43. 9
  44. NIL
  45. |#
  46.  
  47. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  48. ; EXAMPLE 2: process all the odd,even items in a list
  49. (defun oddeven (lst)
  50. (let ((copy (copy-list lst)))
  51. #'(lambda ()
  52. (when lst
  53. (let ((odd (pop copy))
  54. (even (pop copy)))
  55. (and odd
  56. even
  57. (list odd even)))))))
  58.  
  59. (defun !for2 ()
  60. (for (pair (oddeven '(tim m toni f lucie f)))
  61. (print pair)))
  62.  
  63. #|
  64. (LET ((#:STEP1407 (ODDEVEN '(TIM M TONI F LUCIE F))))
  65. (LABELS ((#:NEXT1408 ()
  66. (FUNCALL #:STEP1407))
  67. (#:RUN1409 (PAIR)
  68. (WHEN PAIR (PRINT PAIR) (#:RUN1409 (#:NEXT1408)))))
  69. (#:RUN1409 (#:NEXT1408))))
  70.  
  71. CL-USER> (!for2)
  72.  
  73. (TIM M)
  74. (TONI F)
  75. (LUCIE F)
  76. NIL
  77. |#
  78.  
  79. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  80. ; EXAMPLE 3: fibonacci numbers
  81.  
  82. (defun fibUpToMax (max)
  83. (let ((i1 1)
  84. (i2 1))
  85. #'(lambda ()
  86. (when (<= i1 max)
  87. (let ((tmp i1))
  88. (setf i1 i2)
  89. (setf i2 (+ tmp i2))
  90. tmp)))))
  91.  
  92. (defun !for3 ()
  93. (for (num (fibUpToMax 20))
  94. (print num)))
  95.  
  96. #|
  97. (LET ((#:STEP1410 (FIBUPTOMAX 20)))
  98. (LABELS ((#:NEXT1411 ()
  99. (FUNCALL #:STEP1410))
  100. (#:RUN1412 (NUM)
  101. (WHEN NUM (PRINT NUM) (#:RUN1412 (#:NEXT1411)))))
  102. (#:RUN1412 (#:NEXT1411))))
  103.  
  104. CL-USER> (!for3)
  105.  
  106. 1
  107. 1
  108. 2
  109. 3
  110. 5
  111. 8
  112. 13
  113. NIL
  114. |#
  115.  
  116. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  117. ; EXAMPLE 4:
  118. ; sys admin adds in a delay to your accessing
  119. ; (avoids congestion)
  120.  
  121. (defun recieve (&key (max 100) (buffer 10))
  122. (let ((pause 5))
  123. #'(lambda ()
  124. (let (out)
  125. (dotimes (i buffer)
  126. (decf max)
  127. (if (>= max 0)
  128. (push (cpuIntensiveThing) out)))
  129. (wait (* (random 1.0) pause))
  130. out))))
  131.  
  132. (defun wait (n)
  133. (dotimes (i (round n))
  134. (format t "waiting~a~%" i)))
  135.  
  136. (defun cpuIntensiveThing ()
  137. (random 100))
  138.  
  139. (defun !for4 ()
  140. (for (item (recieve :max 22 :buffer 5))
  141. (format t "~&received ====> ~a~%" item)))
  142.  
  143. #|
  144. (LET ((#:STEP1645 (RECIEVE :MAX 22 :BUFFER 5)))
  145. (LABELS ((#:NEXT1646 ()
  146. (FUNCALL #:STEP1645))
  147. (#:RUN1647 (ITEM)
  148. (WHEN ITEM
  149. (FORMAT T "~&received ====> ~a~%" ITEM)
  150. (#:RUN1647 (#:NEXT1646)))))
  151. (#:RUN1647 (#:NEXT1646))))
  152.  
  153. CL-USER> (load "forall.lisp") (!for4)
  154. waiting0
  155. waiting1
  156. received ====> (83 61 39 71 17)
  157. waiting0
  158. waiting1
  159. waiting2
  160. waiting3
  161. received ====> (39 27 6 39 80)
  162. waiting0
  163. waiting1
  164. received ====> (65 61 41 90 52)
  165. waiting0
  166. waiting1
  167. waiting2
  168. waiting3
  169. received ====> (43 82 29 51 62)
  170. waiting0
  171. waiting1
  172. waiting2
  173. waiting3
  174. waiting4
  175. received ====> (81 1)
  176. waiting0
  177. waiting1
  178. waiting2
  179. NIL
  180. |#

Report this snippet  

You need to login to post a comment.