home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / gnusmalltalk / set.st < prev    next >
Text File  |  1992-02-15  |  6KB  |  249 lines

  1. "======================================================================
  2. |
  3. |   Set Method Definitions
  4. |
  5.  ======================================================================"
  6.  
  7.  
  8. "======================================================================
  9. |
  10. | Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  11. | Written by Steve Byrne.
  12. |
  13. | This file is part of GNU Smalltalk.
  14. |
  15. | GNU Smalltalk is free software; you can redistribute it and/or modify it
  16. | under the terms of the GNU General Public License as published by the Free
  17. | Software Foundation; either version 1, or (at your option) any later version.
  18. | GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
  19. | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  20. | FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  21. | details.
  22. | You should have received a copy of the GNU General Public License along with
  23. | GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
  24. | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
  25. |
  26.  ======================================================================"
  27.  
  28.  
  29. "
  30. |     Change Log
  31. | ============================================================================
  32. | Author       Date       Change 
  33. | sbb         28 Jul 91      #= checks argument type better.
  34. |
  35. | sbb         16 Mar 91      Class creation now separate statement.
  36. |
  37. | sbb         21 Sep 90      Removed printOn: method; the one from Collection is
  38. |              fine.
  39. |
  40. | sbyrne     19 Sep 89      Converted to use real method categories.
  41. |
  42. | sbyrne     25 Apr 89      created.
  43. |
  44. "
  45.  
  46. Collection variableSubclass: #Set
  47.        instanceVariableNames: 'tally'
  48.        classVariableNames: ''
  49.        poolDictionaries: ''
  50.        category: nil
  51. !
  52.  
  53. Set comment:
  54. 'I am the typical set object; I can store any objects uniquely.  I
  55. use the = operator to determine duplication of objects.' !
  56.  
  57. !Set class methodsFor: 'instance creation'!
  58.  
  59. new
  60.     ^self new: 4
  61. !
  62.  
  63. new: anInteger
  64.     ^(super new: anInteger) setTally
  65. !!
  66.  
  67.  
  68.  
  69. !Set methodsFor: 'accessing'!
  70.  
  71. at: index
  72.     self error: 'at: not allowed for Set'
  73. !
  74.  
  75. at: index put: value
  76.     self error: 'at:put: not allowed for Set'
  77. !
  78.  
  79. add: newObject
  80.     | index |
  81.     newObject isNil ifTrue: [ ^newObject ].
  82.     index _ self findObjectIndex: newObject.
  83.     (self basicAt: index) isNil
  84.         ifTrue: [ self basicAt: index put: newObject.
  85.               tally _ tally + 1 ].
  86.     ^newObject
  87. !!
  88.  
  89.  
  90.  
  91. !Set methodsFor: 'Removing from a collection'!
  92.  
  93. remove: oldObject ifAbsent: anExceptionBlock
  94.     | index |
  95.     index _ self findObjectIndexNoGrow: oldObject
  96.                  ifAbsent: [ ^anExceptionBlock value ].
  97.     tally _ tally - 1.
  98.     self rehashObjectsAfter: index.
  99.     ^oldObject
  100. !!
  101.  
  102.  
  103.  
  104. !Set methodsFor: 'testing collections'!
  105.  
  106. includes: anObject
  107.     ^(self basicAt: (self findObjectIndex: anObject)) ~~ nil
  108. !
  109.  
  110. isEmpty
  111.     ^tally == 0
  112. !
  113.  
  114. occurrencesOf: anObject
  115.     "Return the number of occurrences of anObject.  Since we're a set, this
  116.     is either 0 or 1.  Nil is never directly in the set, so we special case
  117.     it here."
  118.     anObject isNil ifTrue: [ ^1 ].
  119.     (self includes: anObject)
  120.         ifTrue: [ ^1 ]
  121.     ifFalse: [ ^0 ]
  122. !
  123.  
  124. size
  125.     ^tally
  126. !
  127.  
  128. hash
  129.     "Return the hash code for the members of the set.  Since order is
  130.     unimportant; we use a commutative operator to compute the hash value."
  131.     ^self inject: tally
  132.           into: [ :hashValue :member | hashValue + member hash ]
  133. !
  134.  
  135. = aSet
  136.     "Returns true if the two sets have the same membership, false if not"
  137.     self class == aSet class
  138.     ifFalse: [ ^false ].
  139.     tally = aSet size  ifFalse: [ ^false ].
  140.     self do: [ :element | (aSet includes: element)
  141.                             ifFalse: [ ^false ] ].
  142.     ^true
  143. !!
  144.  
  145.  
  146.  
  147. !Set methodsFor: 'enumerating the elements of a collection'!
  148.  
  149. do: aBlock
  150.     "Enumerate all the non-nil members of the set"
  151.     1 to: self basicSize do:
  152.         [ :i | (self basicAt: i) notNil
  153.               ifTrue: [ aBlock value: (self basicAt: i) ] ]
  154. !!
  155.  
  156.  
  157.  
  158. !Set methodsFor: 'storing'!
  159.  
  160. storeOn: aStream
  161.     | hasElements |
  162.     aStream nextPutAll: '(Set new'.
  163.     hasElements _ false.
  164.     self do:
  165.         [ :element | aStream nextPutAll: ' add: '.
  166.              element storeOn: aStream.
  167.              aStream nextPut: $;.
  168.              hasElements _ true ].
  169.     hasElements ifTrue: [ aStream nextPutAll: ' yourself' ].
  170.     aStream nextPut: $).
  171. !!
  172.  
  173.  
  174.  
  175. !Set methodsFor: 'private methods'!
  176.  
  177. setTally
  178.     "Instance variable initialization."
  179.     tally _ 0
  180. !
  181.  
  182. rehashObjectsAfter: index
  183.     "Rehashes all the objects in the collection after index to see if any of
  184.     them hash to index.  If so, that object is copied to index, and the
  185.     process repeats with that object's index, until a nil is encountered."
  186.     | i size count element |
  187.     i _ index.
  188.     size _ self basicSize.
  189.     count _ size.
  190.     self basicAt: index put: nil.
  191.     [ count _ count - 1.
  192.       i _ i \\ size + 1.
  193.       element _ self basicAt: i.
  194.       count > 0 and: [ element notNil ] ]
  195.         whileTrue:
  196.         [ self basicAt: i put: nil.
  197.           self basicAt: (self findObjectIndex: element) put: element ].
  198.     ^self
  199. !
  200.  
  201. findObjectIndex: anObject ifFull: aBlock
  202.     "Tries to see if anObject exists as an indexed variable.  If it's searched
  203.     the entire set and the object is not to be found, aBlock is evaluated and
  204.     it's value is returned."
  205.     | index count size newSet element |
  206.     size _ self basicSize.
  207.     index _ anObject hash \\ size + 1.
  208.     count _ size.
  209.     [ count > 0 ]
  210.         whileTrue:
  211.         [ element _ self basicAt: index.
  212.               (element isNil or: [ element = anObject ])
  213.             ifTrue: [ ^index ].
  214.           index _ index \\ size + 1.
  215.           count _ count - 1 ].
  216.     ^aBlock value
  217. !
  218.         
  219. findObjectIndex: anObject
  220.     "Finds the given object in the set and returns its index.  If the set
  221.     doesn't contain the object and there is no nil element, the set is
  222.     grown and then the index of where the object would go is returned."
  223.     ^self findObjectIndex: anObject
  224.            ifFull: [ self grow.
  225.                 self findObjectIndexNoGrow: anObject
  226.                     ifAbsent: [ self error: 'failed to grow a new empty element!!!' ] ]
  227. !
  228.  
  229. findObjectIndexNoGrow: anObject ifAbsent: aBlock
  230.     | index |
  231.     index _ self findObjectIndex: anObject ifFull: [ 0 ].
  232.     index = 0 
  233.         ifTrue: [ ^aBlock value ]
  234.     ifFalse: [ ^index ]
  235. !
  236.  
  237. grow
  238.     | newSet |
  239.     newSet _ self species new: self basicSize + self growSize.
  240.     self do: [ :element | newSet add: element ].
  241.     ^self become: newSet
  242. !
  243.  
  244. growSize
  245.     ^self basicSize        "this will double the size"
  246. !!
  247.