home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / e / queuestack.lha / queuestack.doc < prev    next >
Encoding:
Text File  |  1995-01-27  |  14.2 KB  |  407 lines

  1.  QueueStack v2.0, from the Cheese Olfactory Workshop (written by
  2.  Trey Van Riper) for Amiga E 3.1.
  3.  
  4. It's designed to act as both a stack and a queue.  In fact,
  5. you could change your mind in the middle of either adding or
  6. getting objects into the queuestack to make it act as a
  7. stackqueue.. or whatever.  You can put anything into the
  8. queuestack.. in fact, you could put varying types of data in
  9. the queuestack (of course, you'll have to figure out what
  10. you put in it yourself).  Thanks go to Amiga E as a typeless
  11. language.
  12.  
  13. This second version adds a tremendous amount of
  14. functionality to the queuestack in letting you iterate
  15. through it.  As a result, procFrontToBack/procBackToFront()
  16. have been deleted, in favor of some slightly more useful
  17. phrases (inject/injectBackwards).
  18.  
  19. This second version also allows you to enter '0' as an item,
  20. if you provide another value that can be used as a
  21. replacement instead.  Unfortunately, queuestack needs some
  22. means by which it can determine a non-valid item in order to
  23. perform certain tests.  In the first version, '0' was that
  24. value, however, this prevented '0' from being a value that
  25. could be used in the queuestack (say, if you were working
  26. with strictly integers or something).  Now you may determine
  27. what constitutes a non-valid item (say, you don't expect to
  28. have any integers of a value -1, then you could use -1).
  29.  
  30. Here's what the ShowModule output looks like...:
  31.  
  32. ----------------------------------------------------------------------
  33. ShowModule v1.9 (c) 1992 $#%!
  34. now showing: "queuestack.m"
  35. NOTE: don't use this output in your code, use the module instead.
  36.  
  37. /* this module contains 5496 bytes of code! */
  38.  
  39. /* ... and 56 reloc entries */
  40.  
  41. DEF queuestack_ctrlc
  42. /* 2 private global variable(s) in this module */
  43.  
  44. (---) OBJECT queuestack
  45.         new(a,b)
  46.         addFirst(a)
  47.         addLast(a)
  48.         getFirst()
  49.         getLast()
  50.         getSize()
  51.         addFirstQS(a)
  52.         addLastQS(a)
  53.         inject(a,b)
  54.         injectBackwards(a,b)
  55.         do(a)
  56.         doBackwards(a)
  57.         collect(a)
  58.         collectBackwards(a)
  59.         conform(a)
  60.         detect(a)
  61.         detectBackwards(a)
  62.         reject(a)
  63.         rejectBackwards(a)
  64.         select(a)
  65.         selectBackwards(a)
  66.         asList()
  67.         asListBackwards()
  68.         asQueueStack(a)
  69.         asQueueStackBackwards(a)
  70.         kill()
  71.         end()
  72. (---) ENDOBJECT     /* SIZEOF=20 */
  73.  
  74. (---) OBJECT qsinner
  75. (  4)   next:PTR TO qsinner
  76. (  8)   prev:PTR TO qsinner
  77.         new(a,b)
  78.         inject(a,b)
  79.         injectBackwards(a,b)
  80.         do(a)
  81.         doBackwards(a)
  82.         collect(a,b)
  83.         collectBackwards(a,b)
  84.         conform(a)
  85.         detect(a,b)
  86.         detectBackwards(a,b)
  87.         reject(a,b)
  88.         rejectBackwards(a,b)
  89.         select(a,b)
  90.         selectBackwards(a,b)
  91.         end()
  92. (---) ENDOBJECT     /* SIZEOF=16 */
  93.  
  94. ---------------------------------------------------------------------
  95.  
  96. You should ignore 'OBJECT qsinner'.  I wish I could keep this
  97. object from appearing, but I can't.  So, ignore it and its
  98. associated methods (PROCs).
  99.  
  100. Here are the following functions for queuestack, and how
  101. they work:
  102.  
  103. new(a,b)
  104.  
  105. This is a constructor.  It can also somewhat act like a
  106. destructor to reset a queuestack to NULL again (the
  107. queuestack object is not destructed, only the elements in
  108. the queuestack). If you pass it 'a', 'a' will be put into
  109. the queuestack, just as addFirst() or addLast() would do.
  110.  
  111. Basically, use this function when you don't care about any
  112. of the items in the queuestack, or when you're first
  113. initializing a queuestack.  You MUST call this constructor
  114. if you NEW queuestack (eg. NEW qs.new()).
  115.  
  116. If you pass new() 'b', it will set what constitutes a bad
  117. item.  Without setting 'b', a value of '0' is assumed to be
  118. a bad item, meaning you cannot enter an item with value '0'.
  119. This value was chosen as the default since I guessed most
  120. people would use queuestack for holding pointers to objects,
  121. and no pointer holds a NIL value.  I added this parameter to
  122. allow folks to use queuestack with integers that might
  123. require a '0' value.
  124.  
  125. addFirst/addLast(a)
  126.  
  127. This adds 'a' into the queuestack.  If you use addFirst(),
  128. it will put 'a' on the front of the queuestack, addLast()
  129. will put 'a' on the end of the queuestack.  Nothing to it,
  130. really.
  131.  
  132. getFirst/getLast()
  133.  
  134. This will retrieve an element from the queuestack.  If you
  135. use getFirst(), the element retrieved was on the front of
  136. the queuestack, getLast() gets elements from the end of the
  137. queuestack.  If the queuestack is empty, however, you'll get
  138. a zero element, and queuestack will raise an exception
  139. ("qstk").
  140.  
  141. getSize()
  142.  
  143. This will return how many elements are in the queuestack.  A
  144. good rule of thumb while getting several elements from a
  145. queuestack is to use getSize() to keep you from invoking an
  146. exception:
  147.  
  148.  WHILE a.getSize()
  149.   proc(a.getLast())
  150.  ENDWHILE
  151.  
  152. addFirstQS/addLastQS(in:PTR TO queuestack)
  153.  
  154. These two functions allow you to combine two queuestacks
  155. together.  The queuestack calling this method gets all the
  156. elements in 'in', while 'in' is stripped of all its
  157. elements.  There is currently no way to allow 'in' to keep
  158. its elements while concatenating them to another queuestack.
  159.  
  160. Naturally, whichever function you choose will determine
  161. whether the incoming queuestack is appended or prepended to
  162. the current list (addFirstQS prepends, addLastQS appends).
  163.  
  164. ITERATIVE METHODS
  165.  
  166. The next few methods are iterative methods.  All of them
  167. recurse through the queuestack.  They usually come in pairs
  168. (where appropriate).  Those with 'Backwards' in their name
  169. will iterate through the queuestack backwards rather than
  170. forwards, which may be handy for certain situations.
  171.  
  172. inject/injectBackwards(a,b)
  173.  
  174. NOTE: This replaces what procFirstToLast/procLastToFirst()
  175. did.  Note also that this method can alter the contents of
  176. the list.  It's one of the few methods that can... perhaps
  177. the only method that can.
  178.  
  179. These two methods allow you to iterate through the
  180. queuestack, performing a procedure with the current element
  181. against the previous element.
  182.  
  183. The first parameter is a procedure you've written that takes
  184. two arguments:
  185.  
  186.     PROC a(i,j)
  187.  
  188. The first argument, 'i', will be the value of the current
  189. item in the queuestack.  The second argument, 'j', will be
  190. the value of the previous item in the queuestack.  Whatever
  191. value you decide to return will become the value of the
  192. current item.
  193.  
  194. The second parameter of 'inject()' ('b') is a starting value
  195. to apply.  It will be passed as the second argument of the
  196. first iteration's call to a(i,j) (eg. it will be 'j') just
  197. to get things started.  If left out, the value assumed is
  198. the bad item value you specified in method 'new()' (or '0'
  199. if you didn't specify a bad item value).
  200.  
  201. do/doBackwards(a)
  202.  
  203. These methods simply iterate through the list, performing the
  204. procedure 'a' you've passed to it.  Any value returned by
  205. your procedure is ignored... typically, this procedure might
  206. be used to print the contents of the queuestack.  It will
  207. not change the queuestack.
  208.  
  209. Your procedure should take one argument (the current
  210. element) as a parameter.
  211.  
  212. collect/collectBackwards(a)
  213.  
  214. This method returns a new queuestack where each element is a
  215. result of procedure 'a' you pass to it.  For example, take
  216. the following queuestack contents:
  217.  
  218. IN: 1, 2, 3, 4, 5, 6, 7, 8
  219.  
  220. Your procedure 'a' is:
  221.  
  222. PROC a(i) IS RETURN i+1
  223.  
  224. After 'collect' you would have a new queuestack:
  225.  
  226. OUT: 2, 3, 4, 5, 6, 7, 8, 9
  227.  
  228. So... out:=in.collect({a}) (where 'out:PTR TO queuestack')
  229. would be an appropriate call.
  230.  
  231. conform(a)
  232.  
  233. This may be the only iterative function without a
  234. 'Backwards' counterpart, because it isn't appropriate.
  235. This method performs a test of all the elements in your
  236. queuestack to insure they conform to the procedure you pass
  237. to it.  Your procedure should, again, take one argument (an
  238. item in the queuestack) and return TRUE or FALSE.
  239.  
  240. detect/detectBackwards(a)
  241.  
  242. These methods return the first item in the queuestack that
  243. fits a particular test.  'a' is a procedure taking one
  244. argument and returning TRUE or FALSE.  If it is unable to
  245. detect any items, it will return with whatever value you
  246. entered as a bad item in 'new()' or '0' if no bad item was
  247. specified.
  248.  
  249. reject/rejectBackwards(a)
  250.  
  251. These methods return a new queuestack containing any items
  252. in the queuestack that do not pass the test you pass in
  253. argument 'a'.  'a' is a procedure taking one argument and
  254. returning TRUE or FALSE.  If it is unable to reject any
  255. items, the new queuestack's getSize() will return 0.
  256.  
  257. select/selectBackwards(a)
  258.  
  259. These methods return a new queuestack containing any items
  260. in the queuestack that pass the test you pass in argument
  261. 'a'.  'a' is a procedure taking one argument and returning
  262. TRUE or FALSE.  If it is unable to select any items, the new
  263. queuestack's getSize() will return 0.
  264.  
  265. NOTE: The next two entries are conversion methods.  They'll
  266. help you integrate Amiga E with queuestack more easily.
  267.  
  268. asList/asListBackwards()
  269.  
  270. These methods will create an EList of items in the
  271. queuestack.  Handy if you want to use queuestack to create
  272. ListViews or something.
  273.  
  274. asQueueStack/asQueueStackBackwards(a)
  275.  
  276. These methods will add an EList to the queuestack.  Current
  277. contents in the queuestack will not be effected.  This can
  278. be handy when used with file requesters and other things
  279. that generate ELists (note: do not forget Amiga E's
  280. SetList() command to insure you're really giving QueueStack
  281. an EList... these methods use ListLen()).
  282.  
  283. NOTE: These last two methods are deallocation methods.  Take
  284. care how you use them.
  285.  
  286. kill()
  287.  
  288. This method will go through the queuestack, ENDing all the
  289. items in the queuestack.  It will not END the queuestack
  290. itself, or the instances, therefore it's strongly suggested
  291. this be used only before ENDing the queuestack, or at least
  292. using .new().  This was made as a convenience for people who
  293. want to deallocate a lot of resources at one time in as
  294. simple a way as possible.  Not recommended for integer
  295. queuestacks <grin>.
  296.  
  297. end()
  298.  
  299. This is simply a destructor.  You shouldn't have to mess
  300. with this.. just END your object and this function will be
  301. invoked (as of Amiga E 3.1a).
  302.  
  303. DISTRIBUTING INFORMATION
  304.  
  305. QueueStack is FreeWare.  All I ask is that you acknowledge
  306. that I'm the author of this routine.. nothing more.  You do
  307. not even have to acknowledge me as the author in your
  308. documentation.. I ask that you do not claim work I've done.
  309.  
  310. You may use this module freely in all your software (without
  311. even having to send me a copy of it) without cost.  It's too
  312. primal an object to require any kind of payments or any
  313. nonsense like that, so enjoy it.
  314.  
  315. If Wooter would like, he may include this in his next
  316. version of Amiga E to be released (e:src/pd/class or
  317. wherever).
  318.  
  319. MOTIVATION
  320.  
  321. I wrote this object because I wanted to use it with my Quip
  322. project.  Now that Amiga E has become so strongly Object
  323. Oriented, I'm trying to completely rewrite my Quip program
  324. to take advantage of the improvements to the language.  To
  325. that end, I plan to use this object to help make my life a
  326. little easier (although I think I only needed a queue... but
  327. when I make an object, I try to think as far in the future
  328. as I can).
  329.  
  330. I got the idea to make this a queuestack from reading a
  331. SmallTalk manual.
  332.  
  333. ISSUES
  334.  
  335. Firstly, be very careful while using this tool.  You most
  336. likely will be passing pointers to objects you've
  337. initialized.. as such, these objects will NOT be
  338. de-initialized or re-initialized by queuestack alone.. that
  339. responsibility is left to you.
  340.  
  341. The iterative functions will return the pointers you passed
  342. into it... therefore, when you END a queuestack, any
  343. initialized items in the queuestack will NOT be ENDed... you
  344. must remember to do that yourself by, say, qs.do({endMe}) or
  345. qs.kill().  While Amiga E still deallocates all memory
  346. NEWed when the program ends, this may become an issue if
  347. you're trying to run a server or something.
  348.  
  349. Another point to make; when using any methods that create a
  350. new queuestack, all items that are pointers to other objects
  351. will be pointers to the SAME INVOCATION of that object
  352. (unless, in the case of 'collect', your function returns a
  353. new invocation of your object).  Therefore, if you end that
  354. object while it is still in the queuestack, you may be
  355. asking for trouble.  This can get tricky if someone does a
  356. nqs:=qs.reject({myProc}) followed by a nqs.kill().  If none
  357. of this makes sense, try experimenting a little bit and see
  358. if you can figure it out <grin>.
  359.  
  360. The only potential annoyance with queuestack is a minor
  361. amount of expense.  I traded memory for speed.  While
  362. queuestack isn't likely to eat up GOBS of memory, there are
  363. more memory-efficient ways of doing this same thing, however
  364. one will likely pay a price in speed.
  365.  
  366. Each item put into queuestack will take up 16 bytes of
  367. memory.  Eight of those bytes are used to point to the next
  368. and the previous item in the queuestack (I needed both in
  369. order to handle either direction quickly).  Another four is
  370. used for storing your actual item.  The last four are used
  371. by Amiga E to figure out where my associated procedures are
  372. to process those items if necessary (eg END, new(),
  373. do(), etc).
  374.  
  375. Since memory is fairly cheap these days, I didn't think
  376. anyone would mind terribly.
  377.  
  378. Some recursion is used during the deallocation routines, so
  379. extremely large queuestacks may cause a problem during END if
  380. there isn't enough stack to handle it.  The routine is
  381. pretty bare, though, so it shouldn't be much of a problem at
  382. all.  Same thing goes for iterative routines.
  383.  
  384. FUTURE
  385.  
  386. Well, I thought I had done everything last time, but then I
  387. realized how easy it would be to add these methods in.  I'm
  388. sorry for a slightly lack of compatibility with the old
  389. queuestack, but I hope I've managed to submit this newer
  390. queuestack early enough to avoid any kinds of problems.
  391.  
  392. I may desire to create a sorted list next (via binary tree,
  393. most likely).  If and when I do so, likely, it will contain
  394. similiar methods to these (I had even toyed with the thought
  395. of using a flag to change queuestack into a binary tree...
  396. a thought that still sounds mighty nice to my twisted mind).
  397.  
  398. At the moment, I have little incentive to do so (my current
  399. software developing needs, so far, do not include a need
  400. to sort anything), but if someone is interested in creating
  401. a sorted list based on these methods, please consider
  402. sending me e-mail; perhaps our two objects could be combined
  403. into one module, so a hapless programmer doesn't have to
  404. remember which module to include in his code.
  405.  
  406. May the cow be with you.
  407.