Ver código fonte

Merge pull request #735 from herby/goodies

Collection goodies
Nicolas Petton 10 anos atrás
pai
commit
5775db6535
5 arquivos alterados com 498 adições e 116 exclusões
  1. 6 0
      API-CHANGES.txt
  2. 174 20
      js/Kernel-Collections.js
  3. 225 73
      js/Kernel-Tests.js
  4. 52 7
      st/Kernel-Collections.st
  5. 41 16
      st/Kernel-Tests.st

+ 6 - 0
API-CHANGES.txt

@@ -9,6 +9,12 @@
   + >>uriComponentDecoded
 + Collection
   + >>removeAll
+  + >>ifEmpty:ifNotEmpty:
+  + >>ifNotEmpty:ifEmpty:
+  + >>anyOne
+  + >>noneSatisfy:
+  + >>anySatisfy:
+  + >>allSatisfy:
 
 
 0.12.0:

+ 174 - 20
js/Kernel-Collections.js

@@ -209,6 +209,89 @@ referencedClasses: []
 }),
 smalltalk.Collection);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "allSatisfy:",
+category: 'enumerating',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+var $early={};
+try {
+self._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
+$1=_st(aBlock)._value_(each);
+if(! smalltalk.assert($1)){
+throw $early=[false];
+};
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
+return true;
+}
+catch(e) {if(e===$early)return e[0]; throw e}
+}, function($ctx1) {$ctx1.fill(self,"allSatisfy:",{aBlock:aBlock},smalltalk.Collection)})},
+args: ["aBlock"],
+source: "allSatisfy: aBlock\x0a\x09\x22Evaluate aBlock with the elements of the receiver.\x0a\x09If aBlock returns false for any element return false.\x0a\x09Otherwise return true.\x22\x0a\x0a\x09self do: [:each | (aBlock value: each) ifFalse: [^ false]].\x0a\x09^ true",
+messageSends: ["do:", "ifFalse:", "value:"],
+referencedClasses: []
+}),
+smalltalk.Collection);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "anyOne",
+category: 'adding/removing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $early={};
+try {
+self._ifEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
+return self._error_("Collection is empty");
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
+self._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
+throw $early=[each];
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}));
+return self}
+catch(e) {if(e===$early)return e[0]; throw e}
+}, function($ctx1) {$ctx1.fill(self,"anyOne",{},smalltalk.Collection)})},
+args: [],
+source: "anyOne\x0a\x09\x22Answer a representative sample of the receiver. This method can\x0a\x09be helpful when needing to preinfer the nature of the contents of \x0a\x09semi-homogeneous collections.\x22\x0a\x0a\x09self ifEmpty: [ self error: 'Collection is empty' ].\x0a\x09self do: [:each | ^ each]",
+messageSends: ["ifEmpty:", "error:", "do:"],
+referencedClasses: []
+}),
+smalltalk.Collection);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "anySatisfy:",
+category: 'enumerating',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+var $early={};
+try {
+self._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
+$1=_st(aBlock)._value_(each);
+if(smalltalk.assert($1)){
+throw $early=[true];
+};
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
+return false;
+}
+catch(e) {if(e===$early)return e[0]; throw e}
+}, function($ctx1) {$ctx1.fill(self,"anySatisfy:",{aBlock:aBlock},smalltalk.Collection)})},
+args: ["aBlock"],
+source: "anySatisfy: aBlock\x0a\x09\x22Evaluate aBlock with the elements of the receiver.\x0a\x09If aBlock returns true for any element return true.\x0a\x09Otherwise return false.\x22\x0a\x0a\x09self do: [:each | (aBlock value: each) ifTrue: [^ true]].\x0a\x09^ false",
+messageSends: ["do:", "ifTrue:", "value:"],
+referencedClasses: []
+}),
+smalltalk.Collection);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "asArray",
@@ -318,22 +401,12 @@ fn: function (aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-var $early={};
-try {
-self._do_((function(each){
-return smalltalk.withContext(function($ctx2) {
-$1=_st(aBlock)._value_(each);
-if(smalltalk.assert($1)){
-throw $early=[true];
-};
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
-return false;
-}
-catch(e) {if(e===$early)return e[0]; throw e}
+$1=self._anySatisfy_(aBlock);
+return $1;
 }, function($ctx1) {$ctx1.fill(self,"contains:",{aBlock:aBlock},smalltalk.Collection)})},
 args: ["aBlock"],
-source: "contains: aBlock\x0a\x09\x22Evaluate aBlock with the elements of the receiver.\x0a\x09If aBlock returns true for any element return true.\x0a\x09Otherwise return false.\x22\x0a\x0a\x09self do: [ :each | (aBlock value: each) ifTrue: [ ^ true ] ].\x0a\x09^ false",
-messageSends: ["do:", "ifTrue:", "value:"],
+source: "contains: aBlock\x0a\x09^ self anySatisfy: aBlock",
+messageSends: ["anySatisfy:"],
 referencedClasses: []
 }),
 smalltalk.Collection);
@@ -519,6 +592,30 @@ referencedClasses: []
 }),
 smalltalk.Collection);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "ifEmpty:ifNotEmpty:",
+category: 'testing',
+fn: function (aBlock,anotherBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self._isEmpty();
+if(smalltalk.assert($2)){
+$1=_st(aBlock)._value();
+$ctx1.sendIdx["value"]=1;
+} else {
+$1=_st(anotherBlock)._value();
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"ifEmpty:ifNotEmpty:",{aBlock:aBlock,anotherBlock:anotherBlock},smalltalk.Collection)})},
+args: ["aBlock", "anotherBlock"],
+source: "ifEmpty: aBlock ifNotEmpty: anotherBlock\x0a\x09^ self isEmpty\x0a\x09\x09ifTrue: [ aBlock value ]\x0a\x09\x09ifFalse: [ anotherBlock value ]",
+messageSends: ["ifTrue:ifFalse:", "isEmpty", "value"],
+referencedClasses: []
+}),
+smalltalk.Collection);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "ifNotEmpty:",
@@ -526,13 +623,42 @@ category: 'testing',
 fn: function (aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=self._notEmpty();
-_st($1)._ifTrue_(aBlock);
-return self}, function($ctx1) {$ctx1.fill(self,"ifNotEmpty:",{aBlock:aBlock},smalltalk.Collection)})},
+var $2,$1;
+$2=self._notEmpty();
+if(smalltalk.assert($2)){
+$1=_st(aBlock)._value();
+} else {
+$1=self;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"ifNotEmpty:",{aBlock:aBlock},smalltalk.Collection)})},
 args: ["aBlock"],
-source: "ifNotEmpty: aBlock\x0a\x09self notEmpty ifTrue: aBlock.",
-messageSends: ["ifTrue:", "notEmpty"],
+source: "ifNotEmpty: aBlock\x0a\x09^ self notEmpty\x0a\x09\x09ifTrue: [ aBlock value ]\x0a\x09\x09ifFalse: [ self ]",
+messageSends: ["ifTrue:ifFalse:", "notEmpty", "value"],
+referencedClasses: []
+}),
+smalltalk.Collection);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "ifNotEmpty:ifEmpty:",
+category: 'testing',
+fn: function (aBlock,anotherBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self._notEmpty();
+if(smalltalk.assert($2)){
+$1=_st(aBlock)._value();
+$ctx1.sendIdx["value"]=1;
+} else {
+$1=_st(anotherBlock)._value();
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"ifNotEmpty:ifEmpty:",{aBlock:aBlock,anotherBlock:anotherBlock},smalltalk.Collection)})},
+args: ["aBlock", "anotherBlock"],
+source: "ifNotEmpty: aBlock ifEmpty: anotherBlock\x0a\x09^ self notEmpty\x0a\x09\x09ifTrue: [ aBlock value ]\x0a\x09\x09ifFalse: [ anotherBlock value ]",
+messageSends: ["ifTrue:ifFalse:", "notEmpty", "value"],
 referencedClasses: []
 }),
 smalltalk.Collection);
@@ -641,6 +767,34 @@ referencedClasses: []
 }),
 smalltalk.Collection);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "noneSatisfy:",
+category: 'enumerating',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+var $early={};
+try {
+self._do_((function(item){
+return smalltalk.withContext(function($ctx2) {
+$1=_st(aBlock)._value_(item);
+if(smalltalk.assert($1)){
+throw $early=[false];
+};
+}, function($ctx2) {$ctx2.fillBlock({item:item},$ctx1,1)})}));
+return true;
+}
+catch(e) {if(e===$early)return e[0]; throw e}
+}, function($ctx1) {$ctx1.fill(self,"noneSatisfy:",{aBlock:aBlock},smalltalk.Collection)})},
+args: ["aBlock"],
+source: "noneSatisfy: aBlock\x0a\x09\x22Evaluate aBlock with the elements of the receiver.\x0a\x09If aBlock returns false for all elements return true.\x0a\x09Otherwise return false\x22\x0a\x0a\x09self do: [:item | (aBlock value: item) ifTrue: [^ false]].\x0a\x09^ true",
+messageSends: ["do:", "ifTrue:", "value:"],
+referencedClasses: []
+}),
+smalltalk.Collection);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "notEmpty",

+ 225 - 73
js/Kernel-Tests.js

@@ -1356,6 +1356,95 @@ referencedClasses: []
 }),
 smalltalk.CollectionTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testAllSatisfy",
+category: 'tests',
+fn: function (){
+var self=this;
+var collection,anyOne;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+collection=self._collection();
+anyOne=_st(collection)._anyOne();
+$1=_st(collection)._allSatisfy_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(collection)._includes_(each);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
+$ctx1.sendIdx["allSatisfy:"]=1;
+self._assert_($1);
+self._deny_(_st(collection)._allSatisfy_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(each).__tild_eq(anyOne);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})})));
+return self}, function($ctx1) {$ctx1.fill(self,"testAllSatisfy",{collection:collection,anyOne:anyOne},smalltalk.CollectionTest)})},
+args: [],
+source: "testAllSatisfy\x0a\x09| collection anyOne |\x0a\x09collection := self collection.\x0a\x09anyOne := collection anyOne.\x0a\x09self assert: (collection allSatisfy: [ :each | collection includes: each ]).\x0a\x09self deny: (collection allSatisfy: [ :each | each ~= anyOne ])",
+messageSends: ["collection", "anyOne", "assert:", "allSatisfy:", "includes:", "deny:", "~="],
+referencedClasses: []
+}),
+smalltalk.CollectionTest);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testAnyOne",
+category: 'tests',
+fn: function (){
+var self=this;
+function $Error(){return smalltalk.Error||(typeof Error=="undefined"?nil:Error)}
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+self._should_raise_((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(_st(self._collectionClass())._new())._anyOne();
+$ctx2.sendIdx["anyOne"]=1;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}),$Error());
+$2=self._collection();
+$ctx1.sendIdx["collection"]=1;
+$1=_st($2)._includes_(_st(self._collection())._anyOne());
+self._assert_($1);
+return self}, function($ctx1) {$ctx1.fill(self,"testAnyOne",{},smalltalk.CollectionTest)})},
+args: [],
+source: "testAnyOne\x0a\x09self should: [ self collectionClass new anyOne ] raise: Error.\x0a\x09self assert: (self collection includes: self collection anyOne)",
+messageSends: ["should:raise:", "anyOne", "new", "collectionClass", "assert:", "includes:", "collection"],
+referencedClasses: ["Error"]
+}),
+smalltalk.CollectionTest);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testAnySatisfy",
+category: 'tests',
+fn: function (){
+var self=this;
+var anyOne;
+function $Object(){return smalltalk.Object||(typeof Object=="undefined"?nil:Object)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$3,$2;
+$1=self._collection();
+$ctx1.sendIdx["collection"]=1;
+anyOne=_st($1)._anyOne();
+$3=self._collection();
+$ctx1.sendIdx["collection"]=2;
+$2=_st($3)._anySatisfy_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(each).__eq(anyOne);
+$ctx2.sendIdx["="]=1;
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
+$ctx1.sendIdx["anySatisfy:"]=1;
+self._assert_($2);
+self._deny_(_st(self._collection())._anySatisfy_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(each).__eq(_st($Object())._new());
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})})));
+return self}, function($ctx1) {$ctx1.fill(self,"testAnySatisfy",{anyOne:anyOne},smalltalk.CollectionTest)})},
+args: [],
+source: "testAnySatisfy\x0a\x09| anyOne |\x0a\x09anyOne := self collection anyOne.\x0a\x09self assert: (self collection anySatisfy: [ :each | each = anyOne ]).\x0a\x09self deny: (self collection anySatisfy: [ :each | each = Object new ])",
+messageSends: ["anyOne", "collection", "assert:", "anySatisfy:", "=", "deny:", "new"],
+referencedClasses: ["Object"]
+}),
+smalltalk.CollectionTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testAsArray",
@@ -1496,6 +1585,108 @@ referencedClasses: ["OrderedCollection"]
 }),
 smalltalk.CollectionTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testIfEmptyFamily",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $3,$2,$1,$5,$4,$6,$9,$8,$7,$11,$10,$13,$12,$16,$15,$14,$18,$17,$19;
+$3=self._collectionClass();
+$ctx1.sendIdx["collectionClass"]=1;
+$2=_st($3)._new();
+$ctx1.sendIdx["new"]=1;
+$1=_st($2)._ifEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
+return (42);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
+$ctx1.sendIdx["ifEmpty:"]=1;
+self._assert_equals_($1,(42));
+$ctx1.sendIdx["assert:equals:"]=1;
+$5=self._collection();
+$ctx1.sendIdx["collection"]=1;
+$4=_st($5)._ifEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
+return (42);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
+$6=self._collection();
+$ctx1.sendIdx["collection"]=2;
+self._assert_equals_($4,$6);
+$ctx1.sendIdx["assert:equals:"]=2;
+$9=self._collectionClass();
+$ctx1.sendIdx["collectionClass"]=2;
+$8=_st($9)._new();
+$ctx1.sendIdx["new"]=2;
+$7=_st($8)._ifNotEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
+return (42);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,3)})}));
+$ctx1.sendIdx["ifNotEmpty:"]=1;
+$11=self._collectionClass();
+$ctx1.sendIdx["collectionClass"]=3;
+$10=_st($11)._new();
+$ctx1.sendIdx["new"]=3;
+self._assert_equals_($7,$10);
+$ctx1.sendIdx["assert:equals:"]=3;
+$13=self._collection();
+$ctx1.sendIdx["collection"]=3;
+$12=_st($13)._ifNotEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
+return (42);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,4)})}));
+self._assert_equals_($12,(42));
+$ctx1.sendIdx["assert:equals:"]=4;
+$16=self._collectionClass();
+$ctx1.sendIdx["collectionClass"]=4;
+$15=_st($16)._new();
+$ctx1.sendIdx["new"]=4;
+$14=_st($15)._ifEmpty_ifNotEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
+return (42);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,5)})}),(function(){
+return smalltalk.withContext(function($ctx2) {
+return (999);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,6)})}));
+$ctx1.sendIdx["ifEmpty:ifNotEmpty:"]=1;
+self._assert_equals_($14,(42));
+$ctx1.sendIdx["assert:equals:"]=5;
+$18=self._collection();
+$ctx1.sendIdx["collection"]=4;
+$17=_st($18)._ifEmpty_ifNotEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
+return (42);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,7)})}),(function(){
+return smalltalk.withContext(function($ctx2) {
+return (999);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,8)})}));
+self._assert_equals_($17,(999));
+$ctx1.sendIdx["assert:equals:"]=6;
+$19=_st(_st(self._collectionClass())._new())._ifNotEmpty_ifEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
+return (42);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,9)})}),(function(){
+return smalltalk.withContext(function($ctx2) {
+return (999);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,10)})}));
+$ctx1.sendIdx["ifNotEmpty:ifEmpty:"]=1;
+self._assert_equals_($19,(999));
+$ctx1.sendIdx["assert:equals:"]=7;
+self._assert_equals_(_st(self._collection())._ifNotEmpty_ifEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
+return (42);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,11)})}),(function(){
+return smalltalk.withContext(function($ctx2) {
+return (999);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,12)})})),(42));
+return self}, function($ctx1) {$ctx1.fill(self,"testIfEmptyFamily",{},smalltalk.CollectionTest)})},
+args: [],
+source: "testIfEmptyFamily\x0a\x09self assert: (self collectionClass new ifEmpty: [ 42 ]) equals: 42.\x0a\x09self assert: (self collection ifEmpty: [ 42 ]) equals: self collection.\x0a\x0a\x09self assert: (self collectionClass new ifNotEmpty: [ 42 ]) equals: self collectionClass new.\x0a\x09self assert: (self collection ifNotEmpty: [ 42 ]) equals: 42.\x0a\x09\x0a\x09self assert: (self collectionClass new ifEmpty: [ 42 ] ifNotEmpty: [ 999 ]) equals: 42.\x0a\x09self assert: (self collection ifEmpty: [ 42 ] ifNotEmpty: [ 999 ]) equals: 999.\x0a\x0a\x09self assert: (self collectionClass new ifNotEmpty: [ 42 ] ifEmpty: [ 999 ]) equals: 999.\x0a\x09self assert: (self collection ifNotEmpty: [ 42 ] ifEmpty: [ 999 ]) equals: 42",
+messageSends: ["assert:equals:", "ifEmpty:", "new", "collectionClass", "collection", "ifNotEmpty:", "ifEmpty:ifNotEmpty:", "ifNotEmpty:ifEmpty:"],
+referencedClasses: []
+}),
+smalltalk.CollectionTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testIsEmpty",
@@ -1516,6 +1707,40 @@ referencedClasses: []
 }),
 smalltalk.CollectionTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testNoneSatisfy",
+category: 'tests',
+fn: function (){
+var self=this;
+var anyOne;
+function $Object(){return smalltalk.Object||(typeof Object=="undefined"?nil:Object)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$3,$2;
+$1=self._collection();
+$ctx1.sendIdx["collection"]=1;
+anyOne=_st($1)._anyOne();
+$3=self._collection();
+$ctx1.sendIdx["collection"]=2;
+$2=_st($3)._noneSatisfy_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(each).__eq(anyOne);
+$ctx2.sendIdx["="]=1;
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
+$ctx1.sendIdx["noneSatisfy:"]=1;
+self._deny_($2);
+self._assert_(_st(self._collection())._noneSatisfy_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(each).__eq(_st($Object())._new());
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})})));
+return self}, function($ctx1) {$ctx1.fill(self,"testNoneSatisfy",{anyOne:anyOne},smalltalk.CollectionTest)})},
+args: [],
+source: "testNoneSatisfy\x0a\x09| anyOne |\x0a\x09anyOne := self collection anyOne.\x0a\x09self deny: (self collection noneSatisfy: [ :each | each = anyOne ]).\x0a\x09self assert: (self collection noneSatisfy: [ :each | each = Object new ])",
+messageSends: ["anyOne", "collection", "deny:", "noneSatisfy:", "=", "assert:", "new"],
+referencedClasses: ["Object"]
+}),
+smalltalk.CollectionTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testRemoveAll",
@@ -1664,42 +1889,6 @@ referencedClasses: []
 }),
 smalltalk.IndexableCollectionTest);
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testContains",
-category: 'tests',
-fn: function (){
-var self=this;
-var collection;
-function $Object(){return smalltalk.Object||(typeof Object=="undefined"?nil:Object)}
-return smalltalk.withContext(function($ctx1) { 
-var $2,$4,$3,$1;
-collection=self._collection();
-$ctx1.sendIdx["collection"]=1;
-$2=self._collection();
-$ctx1.sendIdx["collection"]=2;
-$1=_st($2)._contains_((function(each){
-return smalltalk.withContext(function($ctx2) {
-$4=self._collection();
-$ctx2.sendIdx["collection"]=3;
-$3=_st($4)._first();
-return _st(each).__eq($3);
-$ctx2.sendIdx["="]=1;
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
-$ctx1.sendIdx["contains:"]=1;
-self._assert_($1);
-self._deny_(_st(self._collection())._contains_((function(each){
-return smalltalk.withContext(function($ctx2) {
-return _st(each).__eq(_st($Object())._new());
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})})));
-return self}, function($ctx1) {$ctx1.fill(self,"testContains",{collection:collection},smalltalk.IndexableCollectionTest)})},
-args: [],
-source: "testContains\x0a\x09| collection |\x0a\x09collection := self collection.\x0a\x09\x0a\x09self assert: (self collection contains: [ :each | each = self collection first ]).\x0a\x09self deny: (self collection contains: [ :each | each = Object new ])",
-messageSends: ["collection", "assert:", "contains:", "=", "first", "deny:", "new"],
-referencedClasses: ["Object"]
-}),
-smalltalk.IndexableCollectionTest);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testIndexOf",
@@ -1855,43 +2044,6 @@ referencedClasses: ["Error"]
 }),
 smalltalk.HashedCollectionTest);
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "testContains",
-category: 'tests',
-fn: function (){
-var self=this;
-var collection;
-function $Object(){return smalltalk.Object||(typeof Object=="undefined"?nil:Object)}
-return smalltalk.withContext(function($ctx1) { 
-var $2,$5,$4,$3,$1;
-collection=self._collection();
-$ctx1.sendIdx["collection"]=1;
-$2=self._collection();
-$ctx1.sendIdx["collection"]=2;
-$1=_st($2)._contains_((function(each){
-return smalltalk.withContext(function($ctx2) {
-$5=self._collection();
-$ctx2.sendIdx["collection"]=3;
-$4=_st($5)._values();
-$3=_st($4)._first();
-return _st(each).__eq($3);
-$ctx2.sendIdx["="]=1;
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
-$ctx1.sendIdx["contains:"]=1;
-self._assert_($1);
-self._deny_(_st(self._collection())._contains_((function(each){
-return smalltalk.withContext(function($ctx2) {
-return _st(each).__eq(_st($Object())._new());
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})})));
-return self}, function($ctx1) {$ctx1.fill(self,"testContains",{collection:collection},smalltalk.HashedCollectionTest)})},
-args: [],
-source: "testContains\x0a\x09| collection |\x0a\x09collection := self collection.\x0a\x09\x0a\x09self assert: (self collection contains: [ :each | each = self collection values first ]).\x0a\x09self deny: (self collection contains: [ :each | each = Object new ])",
-messageSends: ["collection", "assert:", "contains:", "=", "first", "values", "deny:", "new"],
-referencedClasses: ["Object"]
-}),
-smalltalk.HashedCollectionTest);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testFrom",

+ 52 - 7
st/Kernel-Collections.st

@@ -85,6 +85,15 @@ addAll: aCollection
 	^ aCollection
 !
 
+anyOne
+	"Answer a representative sample of the receiver. This method can
+	be helpful when needing to preinfer the nature of the contents of 
+	semi-homogeneous collections."
+
+	self ifEmpty: [ self error: 'Collection is empty' ].
+	self do: [:each | ^ each]
+!
+
 remove: anObject
 	^ self remove: anObject ifAbsent: [ self errorNotFound ]
 !
@@ -140,6 +149,24 @@ copyWithoutAll: aCollection
 
 !Collection methodsFor: 'enumerating'!
 
+allSatisfy: aBlock
+	"Evaluate aBlock with the elements of the receiver.
+	If aBlock returns false for any element return false.
+	Otherwise return true."
+
+	self do: [:each | (aBlock value: each) ifFalse: [^ false]].
+	^ true
+!
+
+anySatisfy: aBlock
+	"Evaluate aBlock with the elements of the receiver.
+	If aBlock returns true for any element return true.
+	Otherwise return false."
+
+	self do: [:each | (aBlock value: each) ifTrue: [^ true]].
+	^ false
+!
+
 collect: aBlock
 	| stream |
 	stream := self class new writeStream.
@@ -192,6 +219,15 @@ intersection: aCollection
 	^ self class withAll: outputSet asArray
 !
 
+noneSatisfy: aBlock
+	"Evaluate aBlock with the elements of the receiver.
+	If aBlock returns false for all elements return true.
+	Otherwise return false"
+
+	self do: [:item | (aBlock value: item) ifTrue: [^ false]].
+	^ true
+!
+
 reject: aBlock
 	^ self select: [ :each | (aBlock value: each) = false ]
 !
@@ -229,12 +265,7 @@ putOn: aStream
 !Collection methodsFor: 'testing'!
 
 contains: aBlock
-	"Evaluate aBlock with the elements of the receiver.
-	If aBlock returns true for any element return true.
-	Otherwise return false."
-
-	self do: [ :each | (aBlock value: each) ifTrue: [ ^ true ] ].
-	^ false
+	^ self anySatisfy: aBlock
 !
 
 ifEmpty: aBlock
@@ -245,8 +276,22 @@ ifEmpty: aBlock
 		ifFalse: [ self ]
 !
 
+ifEmpty: aBlock ifNotEmpty: anotherBlock
+	^ self isEmpty
+		ifTrue: [ aBlock value ]
+		ifFalse: [ anotherBlock value ]
+!
+
 ifNotEmpty: aBlock
-	self notEmpty ifTrue: aBlock.
+	^ self notEmpty
+		ifTrue: [ aBlock value ]
+		ifFalse: [ self ]
+!
+
+ifNotEmpty: aBlock ifEmpty: anotherBlock
+	^ self notEmpty
+		ifTrue: [ aBlock value ]
+		ifFalse: [ anotherBlock value ]
 !
 
 includes: anObject

+ 41 - 16
st/Kernel-Tests.st

@@ -416,6 +416,26 @@ isCollectionReadOnly
 
 !CollectionTest methodsFor: 'tests'!
 
+testAllSatisfy
+	| collection anyOne |
+	collection := self collection.
+	anyOne := collection anyOne.
+	self assert: (collection allSatisfy: [ :each | collection includes: each ]).
+	self deny: (collection allSatisfy: [ :each | each ~= anyOne ])
+!
+
+testAnyOne
+	self should: [ self collectionClass new anyOne ] raise: Error.
+	self assert: (self collection includes: self collection anyOne)
+!
+
+testAnySatisfy
+	| anyOne |
+	anyOne := self collection anyOne.
+	self assert: (self collection anySatisfy: [ :each | each = anyOne ]).
+	self deny: (self collection anySatisfy: [ :each | each = Object new ])
+!
+
 testAsArray
 	self
 		assertSameContents: self collection
@@ -463,11 +483,32 @@ testDo
 		as: newCollection
 !
 
+testIfEmptyFamily
+	self assert: (self collectionClass new ifEmpty: [ 42 ]) equals: 42.
+	self assert: (self collection ifEmpty: [ 42 ]) equals: self collection.
+
+	self assert: (self collectionClass new ifNotEmpty: [ 42 ]) equals: self collectionClass new.
+	self assert: (self collection ifNotEmpty: [ 42 ]) equals: 42.
+	
+	self assert: (self collectionClass new ifEmpty: [ 42 ] ifNotEmpty: [ 999 ]) equals: 42.
+	self assert: (self collection ifEmpty: [ 42 ] ifNotEmpty: [ 999 ]) equals: 999.
+
+	self assert: (self collectionClass new ifNotEmpty: [ 42 ] ifEmpty: [ 999 ]) equals: 999.
+	self assert: (self collection ifNotEmpty: [ 42 ] ifEmpty: [ 999 ]) equals: 42
+!
+
 testIsEmpty
 	self assert: self collectionClass new isEmpty.
 	self deny: self collection isEmpty
 !
 
+testNoneSatisfy
+	| anyOne |
+	anyOne := self collection anyOne.
+	self deny: (self collection noneSatisfy: [ :each | each = anyOne ]).
+	self assert: (self collection noneSatisfy: [ :each | each = Object new ])
+!
+
 testRemoveAll
 	self assert: (self collection removeAll; yourself) equals: self collectionClass new
 !
@@ -513,14 +554,6 @@ testAtIfAbsent
 	self assert: (self collection at: (self collection size + 1) ifAbsent: [ 'none' ]) equals: 'none'
 !
 
-testContains
-	| collection |
-	collection := self collection.
-	
-	self assert: (self collection contains: [ :each | each = self collection first ]).
-	self deny: (self collection contains: [ :each | each = Object new ])
-!
-
 testIndexOf
 	self assert: (self collection indexOf: 2) equals: 2.
 	self should: [ self collection indexOf: 999 ] raise: Error.
@@ -560,14 +593,6 @@ testAt
 	self should: [ self collection at: 5 ] raise: Error
 !
 
-testContains
-	| collection |
-	collection := self collection.
-	
-	self assert: (self collection contains: [ :each | each = self collection values first ]).
-	self deny: (self collection contains: [ :each | each = Object new ])
-!
-
 testFrom
 "Accept a collection of associations."
 | associations |