[PATCH] Provide a common superclass of Collection and Stream

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] Provide a common superclass of Collection and Stream

Paolo Bonzini-2
The class is called Iterable and it implements, together with #do:, some
more methods (a few of which are currently duplicated in the two
hierarchies).  More will come later.

Paolo

diff --git a/kernel/Collection.st b/kernel/Collection.st
index 2848690..47c8eb2 100644
--- a/kernel/Collection.st
+++ b/kernel/Collection.st
@@ -32,7 +32,7 @@
 
 
 
-Object subclass: Collection [
+Iterable subclass: Collection [
     
     <category: 'Collections'>
     <comment: 'I am an abstract class.  My instances are collections of objects.  My
@@ -316,26 +316,6 @@ of objects.'>
  ^Generator on: self do: [ :gen :each | gen yield: each ]
     ]
 
-    do: aBlock [
- "Enumerate each object of the receiver, passing them to aBlock"
-
- <category: 'enumeration'>
- self subclassResponsibility
-    ]
-
-    do: aBlock separatedBy: separatorBlock [
- "Enumerate each object of the receiver, passing them to aBlock.
- Between every two invocations of aBlock, invoke separatorBlock"
-
- <category: 'enumeration'>
- | first |
- first := true.
- self do:
- [:each |
- first ifTrue: [first := false] ifFalse: [separatorBlock value].
- aBlock value: each]
-    ]
-
     select: aBlock [
  "Answer a new instance of a Collection containing all the elements
  in the receiver which, when passed to aBlock, answer true"
@@ -371,27 +351,6 @@ of objects.'>
  ^newCollection
     ]
 
-    detect: aBlock ifNone: exceptionBlock [
- "Search the receiver for an element for which aBlock returns true.
- If some does, answer it. If none does, answer the result of evaluating
- aBlock"
-
- <category: 'enumeration'>
- self do: [:element | (aBlock value: element) ifTrue: [^element]].
- ^exceptionBlock value
-    ]
-
-    count: aBlock [
- "Count the elements of the receiver for which aBlock returns true,
- and return their number."
-
- <category: 'enumeration'>
- | count |
- count := 0.
- self do: [:element | (aBlock value: element) ifTrue: [count := count + 1]].
- ^count
-    ]
-
     gather: aBlock [
  "Answer a new instance of a Collection containing all the results
  of evaluating aBlock, joined together.  aBlock should return
@@ -402,91 +361,6 @@ of objects.'>
  ^(self collect: aBlock) join
     ]
 
-    allSatisfy: aBlock [
- "Search the receiver for an element for which aBlock returns false.
- Answer true if none does, false otherwise."
-
- <category: 'enumeration'>
- self do: [:element | (aBlock value: element) ifFalse: [^false]].
- ^true
-    ]
-
-    noneSatisfy: aBlock [
- "Search the receiver for an element for which aBlock returns true.
- Answer true if none does, false otherwise."
-
- <category: 'enumeration'>
- self do: [:element | (aBlock value: element) ifTrue: [^false]].
- ^true
-    ]
-
-    anySatisfy: aBlock [
- "Search the receiver for an element for which aBlock returns true.
- Answer true if some does, false otherwise."
-
- <category: 'enumeration'>
- self do: [:element | (aBlock value: element) ifTrue: [^true]].
- ^false
-    ]
-
-    conform: aBlock [
- "Search the receiver for an element for which aBlock returns false.
- Answer true if none does, false otherwise."
-
- <category: 'enumeration'>
- self do: [:element | (aBlock value: element) ifFalse: [^false]].
- ^true
-    ]
-
-    contains: aBlock [
- "Search the receiver for an element for which aBlock returns true.
- Answer true if some does, false otherwise."
-
- <category: 'enumeration'>
- self do: [:element | (aBlock value: element) ifTrue: [^true]].
- ^false
-    ]
-
-    detect: aBlock [
- "Search the receiver for an element for which aBlock returns true.
- If some does, answer it. If none does, fail"
-
- <category: 'enumeration'>
- ^self detect: aBlock
-    ifNone: [SystemExceptions.NotFound signal: 'object not found']
-    ]
-
-    fold: binaryBlock [
- "First, pass to binaryBlock the first and second elements of the
- receiver; for each subsequent element, pass the result of the previous
- evaluation and an element. Answer the result of the last invocation,
- or the first element if the collection has size 1.  Fail if the collection
- is empty."
-
- <category: 'enumeration'>
- | result marker |
- self isEmpty ifTrue: [^SystemExceptions.EmptyCollection signalOn: self].
- result := marker := Object new.
- self do:
- [:element |
- result := result == marker
-    ifTrue: [element]
-    ifFalse: [binaryBlock value: result value: element]].
- ^result
-    ]
-
-    inject: thisValue into: binaryBlock [
- "First, pass to binaryBlock thisValue and the first element of the
- receiver; for each subsequent element, pass the result of the previous
- evaluation and an element. Answer the result of the last invocation."
-
- <category: 'enumeration'>
- | result |
- result := thisValue.
- self do: [:element | result := binaryBlock value: result value: element].
- ^result
-    ]
-
     asArray [
  "Answer an Array containing all the elements in the receiver"
 
diff --git a/kernel/Iterable.st b/kernel/Iterable.st
new file mode 100644
index 0000000..71f93ef
--- /dev/null
+++ b/kernel/Iterable.st
@@ -0,0 +1,205 @@
+"======================================================================
+|
+|   Iterable Method Definitions
+|
+|
+ ======================================================================"
+
+"======================================================================
+|
+| Copyright 2008 Free Software Foundation, Inc.
+| Written by Paolo Bonzini.
+|
+| This file is part of the GNU Smalltalk class library.
+|
+| The GNU Smalltalk class library is free software; you can redistribute it
+| and/or modify it under the terms of the GNU Lesser General Public License
+| as published by the Free Software Foundation; either version 2.1, or (at
+| your option) any later version.
+|
+| The GNU Smalltalk class library is distributed in the hope that it will be
+| useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+| General Public License for more details.
+|
+| You should have received a copy of the GNU Lesser General Public License
+| along with the GNU Smalltalk class library; see the file COPYING.LIB.
+| If not, write to the Free Software Foundation, 59 Temple Place - Suite
+| 330, Boston, MA 02110-1301, USA.  
+|
+ ======================================================================"
+
+
+
+Object subclass: Iterable [
+    
+    <category: 'Collections'>
+    <comment: 'I am an abstract class.  My instances are collections of objects
+that can be iterated.  The details on how they can be mutated (if at
+all possible) are left to the subclasses.'>
+
+    Iterable class >> isUnicode [
+ "Answer true; the receiver is able to store arbitrary
+ Unicode characters."
+
+ <category: 'multibyte encodings'>
+ self subclassResponsibility
+    ]
+
+    readStream [
+        "Answer a stream that gives elements of the receiver"
+
+ <category: 'enumeration'>
+ self subclassResponsibility
+    ]
+
+    do: aBlock [
+ "Enumerate each object of the receiver, passing them to aBlock"
+
+ <category: 'enumeration'>
+ self subclassResponsibility
+    ]
+
+    do: aBlock separatedBy: separatorBlock [
+ "Enumerate each object of the receiver, passing them to aBlock.
+ Between every two invocations of aBlock, invoke separatorBlock"
+
+ <category: 'enumeration'>
+ | first |
+ first := true.
+ self do:
+ [:each |
+ first ifTrue: [first := false] ifFalse: [separatorBlock value].
+ aBlock value: each]
+    ]
+
+    select: aBlock [
+ "Answer a new instance of a Collection containing all the elements
+ in the receiver which, when passed to aBlock, answer true"
+
+ <category: 'enumeration'>
+ self subclassResponsibility
+    ]
+
+    reject: aBlock [
+ "Answer a new instance of a Collection containing all the elements
+ in the receiver which, when passed to aBlock, don't answer true"
+
+ <category: 'enumeration'>
+ self subclassResponsibility
+    ]
+
+    collect: aBlock [
+ "Answer a new instance of a Collection containing all the results
+ of evaluating aBlock passing each of the receiver's elements"
+
+ <category: 'enumeration'>
+ self subclassResponsibility
+    ]
+
+    detect: aBlock ifNone: exceptionBlock [
+ "Search the receiver for an element for which aBlock returns true.
+ If some does, answer it. If none does, answer the result of evaluating
+ aBlock"
+
+ <category: 'enumeration'>
+ self do: [:element | (aBlock value: element) ifTrue: [^element]].
+ ^exceptionBlock value
+    ]
+
+    count: aBlock [
+ "Count the elements of the receiver for which aBlock returns true,
+ and return their number."
+
+ <category: 'enumeration'>
+ | count |
+ count := 0.
+ self do: [:element | (aBlock value: element) ifTrue: [count := count + 1]].
+ ^count
+    ]
+
+    allSatisfy: aBlock [
+ "Search the receiver for an element for which aBlock returns false.
+ Answer true if none does, false otherwise."
+
+ <category: 'enumeration'>
+ self do: [:element | (aBlock value: element) ifFalse: [^false]].
+ ^true
+    ]
+
+    noneSatisfy: aBlock [
+ "Search the receiver for an element for which aBlock returns true.
+ Answer true if none does, false otherwise."
+
+ <category: 'enumeration'>
+ self do: [:element | (aBlock value: element) ifTrue: [^false]].
+ ^true
+    ]
+
+    anySatisfy: aBlock [
+ "Search the receiver for an element for which aBlock returns true.
+ Answer true if some does, false otherwise."
+
+ <category: 'enumeration'>
+ self do: [:element | (aBlock value: element) ifTrue: [^true]].
+ ^false
+    ]
+
+    conform: aBlock [
+ "Search the receiver for an element for which aBlock returns false.
+ Answer true if none does, false otherwise."
+
+ <category: 'enumeration'>
+ self do: [:element | (aBlock value: element) ifFalse: [^false]].
+ ^true
+    ]
+
+    contains: aBlock [
+ "Search the receiver for an element for which aBlock returns true.
+ Answer true if some does, false otherwise."
+
+ <category: 'enumeration'>
+ self do: [:element | (aBlock value: element) ifTrue: [^true]].
+ ^false
+    ]
+
+    detect: aBlock [
+ "Search the receiver for an element for which aBlock returns true.
+ If some does, answer it. If none does, fail"
+
+ <category: 'enumeration'>
+ ^self detect: aBlock
+    ifNone: [SystemExceptions.NotFound signal: 'object not found']
+    ]
+
+    fold: binaryBlock [
+ "First, pass to binaryBlock the first and second elements of the
+ receiver; for each subsequent element, pass the result of the previous
+ evaluation and an element. Answer the result of the last invocation,
+ or the first element if the collection has size 1.  Fail if the collection
+ is empty."
+
+ <category: 'enumeration'>
+ | result marker |
+ self isEmpty ifTrue: [^SystemExceptions.EmptyCollection signalOn: self].
+ result := marker := Object new.
+ self do:
+ [:element |
+ result := result == marker
+    ifTrue: [element]
+    ifFalse: [binaryBlock value: result value: element]].
+ ^result
+    ]
+
+    inject: thisValue into: binaryBlock [
+ "First, pass to binaryBlock thisValue and the first element of the
+ receiver; for each subsequent element, pass the result of the previous
+ evaluation and an element. Answer the result of the last invocation."
+
+ <category: 'enumeration'>
+ | result |
+ result := thisValue.
+ self do: [:element | result := binaryBlock value: result value: element].
+ ^result
+    ]
+]
diff --git a/kernel/Stream.st b/kernel/Stream.st
index 32ca159..b366db0 100644
--- a/kernel/Stream.st
+++ b/kernel/Stream.st
@@ -32,7 +32,7 @@
 
 
 
-Object subclass: Stream [
+Iterable subclass: Stream [
     
     <category: 'Streams'>
     <comment: 'I am an abstract class that provides interruptable sequential access to
diff --git a/kernel/StreamOps.st b/kernel/StreamOps.st
index 9c6e4d1..118bfe5 100644
--- a/kernel/StreamOps.st
+++ b/kernel/StreamOps.st
@@ -669,32 +669,6 @@ Stream extend [
  ^self peekFor: aCharacter
     ]
 
-    fold: aBlock [
- "First, pass to binaryBlock the first and second elements of the
- receiver; for each subsequent element, pass the result of the previous
- evaluation and an element. Answer the result of the last invocation,
- or the first element if the stream has a single element."
-
- <category: 'filtering'>
- | result |
- result := self next.
- [self atEnd] whileFalse: [result := aBlock value: result value: self next].
- ^result
-    ]
-
-    inject: value into: aBlock [
- "First, pass to binaryBlock value and the first element of the
- receiver; for each subsequent element, pass the result of the previous
- evaluation and an element. Answer the result of the last invocation,
- or value if the stream is empty."
-
- <category: 'filtering'>
- | result |
- result := value.
- [self atEnd] whileFalse: [result := aBlock value: result value: self next].
- ^result
-    ]
-
     select: aBlock [
  "Answer a new stream that only returns those objects for which aBlock
  returns true.  Note that the returned stream will not be positionable."
diff --git a/libgst/dict.c b/libgst/dict.c
index 3871ed6..ac3ed14 100644
--- a/libgst/dict.c
+++ b/libgst/dict.c
@@ -124,6 +124,7 @@ OOP _gst_identity_dictionary_class = NULL;
 OOP _gst_identity_set_class = NULL;
 OOP _gst_integer_class = NULL;
 OOP _gst_interval_class = NULL;
+OOP _gst_iterable_class = NULL;
 OOP _gst_large_integer_class = NULL;
 OOP _gst_large_negative_integer_class = NULL;
 OOP _gst_large_positive_integer_class = NULL;
@@ -434,7 +435,11 @@ static const class_definition class_info[] = {
    GST_ISP_FIXED, true, 1,
    "SymLink", "symbol", NULL, NULL },
 
-  {&_gst_collection_class, &_gst_object_class,
+  {&_gst_iterable_class, &_gst_object_class,
+   GST_ISP_FIXED, false, 0,
+   "Iterable", NULL, NULL, NULL },
+
+  {&_gst_collection_class, &_gst_iterable_class,
    GST_ISP_FIXED, false, 0,
    "Collection", NULL, NULL, NULL },
 
@@ -593,7 +598,7 @@ static const class_definition class_info[] = {
    GST_ISP_POINTER, false, 0,
    "SystemDictionary", NULL, NULL, NULL },
 
-  {&_gst_stream_class, &_gst_object_class,
+  {&_gst_stream_class, &_gst_iterable_class,
    GST_ISP_FIXED, false, 0,
    "Stream", NULL, NULL, NULL },
 
diff --git a/libgst/dict.h b/libgst/dict.h
index e01293e..438f091 100644
--- a/libgst/dict.h
+++ b/libgst/dict.h
@@ -381,6 +381,7 @@ extern OOP _gst_homed_association_class ATTRIBUTE_HIDDEN;
 extern OOP _gst_identity_dictionary_class ATTRIBUTE_HIDDEN;
 extern OOP _gst_identity_set_class ATTRIBUTE_HIDDEN;
 extern OOP _gst_integer_class ATTRIBUTE_HIDDEN;
+extern OOP _gst_iterable_class ATTRIBUTE_HIDDEN;
 extern OOP _gst_interval_class ATTRIBUTE_HIDDEN;
 extern OOP _gst_large_integer_class ATTRIBUTE_HIDDEN;
 extern OOP _gst_large_negative_integer_class ATTRIBUTE_HIDDEN;
diff --git a/libgst/files.c b/libgst/files.c
index 6d3736b..0afb81b 100644
--- a/libgst/files.c
+++ b/libgst/files.c
@@ -188,14 +188,15 @@ static const char standard_files[] = {
   "Link.st\0"
   "Process.st\0"
   "CallinProcess.st\0"
-  "CompildCode.st\0"
-  "CompildMeth.st\0"
-  "CompiledBlk.st\0"
+  "Iterable.st\0"
   "Collection.st\0"
   "SeqCollect.st\0"
   "LinkedList.st\0"
   "Semaphore.st\0"
   "ArrayColl.st\0"
+  "CompildCode.st\0"
+  "CompildMeth.st\0"
+  "CompiledBlk.st\0"
   "Array.st\0"
   "ByteArray.st\0"
   "CharArray.st\0"
diff --git a/packages.xml b/packages.xml
index 9e7b75a..5a820f5 100644
--- a/packages.xml
+++ b/packages.xml
@@ -83,6 +83,7 @@
   <file>CompildMeth.st</file>
   <file>LookupTable.st</file>
   <file>RunArray.st</file>
+  <file>Iterable.st</file>
   <file>ArrayColl.st</file>
   <file>CompiledBlk.st</file>
   <file>Magnitude.st</file>

_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk