CodeFoo

This page describes some of the most useful additions for Smalltalk, you can find more of them in the CodeFooDevelopment bundle on How to access the SCG visualworks store.


Symbol » value: anObject

The simplest little extension that could possibly make a big difference. The extension allows to use symbols as unary blocks, for example you may replace

    coll do: \[ :each | each unaryMessage ]

with

    coll do: #unaryMessage

There is a package SymbolValue both on How to access the SCG visualworks store as well as public store. For more information, please refer to How valueable is a Symbol? by Travis Griggs.

* » asSortBlock

Answer a sort block based on the receiver, implemented as

``` Symbol >> asSortBlock ^\[ :a :b | (a perform: self) > asSortBlock self numArgs = 1 ifTrue: \[ ^\[ :a :b | (self value: a)

Please note that, to improve execution speed, CodeFoo's actual implementation does some magic to generate an unbound block rather than a full block bound the receiver.

BlockClosure » *

Other useful extensions of blocks includes


Character » isSpace

Answer whether the receiver is a space.

CharacterArray » *

Useful extensions of strings includes

in particular those dealing with pre- and suffices are very useful


Collection » transitiveClosure: unaryBlock

Answer the transitive closure of the receiver, that is, all elements in the receiver plus any element reachable using the unary block. For example

    (Array with: Object) transitiveClosure: \[ :each | each subclasses ]

returns the same as

    Object withAllSubclasses

Implemented as follows

``` Collection >> transitiveClosure: unaryBlock ^self species withAll: (self asSet transitiveClosure: unaryBlock) ``` ``` Set >> transitiveClosure: unaryBlock | closure candidates | closure := self species new. candidates := self copy. \[ candidates isEmpty ] whileFalse: \[ | element | element := closure add: candidates removeAny. (unaryBlock value: element) asCollectionDo: \[ :each | closure find: each ifAbsent: \[ candidates add: each ] ]]. ^closure. ```

Please not that the term closure in "transitive closure" refers to the mathematics meaning of transitive closure (see Wikipedia) rather than to computer science terminology, this is very confusing and a better naming for the method is welcome.

Set » removeAny

Implemented as

``` Set >> removeAny ^self remove: self any ```

* » asCollectionDo: aBlock

General purpose implementation of #do:, implemented as

``` UndefinedObject >> asCollectionDo: aBlock ^self ``` ``` Object >> asCollectionDo: aBlock aBlock value: self ``` ``` Collection >> asCollectionDo: aBlock self do: aBlock ``` ``` CharacterArray >> asCollectionDo: aBlock aBlock value: self ```

Please note, we assume that strings are to be treated as objects rather than as collection.

* » asCollection

Implemented analog to #asCollectionDo: as

``` UndefinedObject >> asCollection ^#() ``` ``` Object >> asCollection ^Array with: self ``` ``` Collection >> asCollection ^self ``` ``` CharacterArray >> asCollection ^Array with: self ```

Please note, we assume that strings are to be treated as objects rather than as collection.

Collection » *

Other useful extensions of collection include set operations,

mathematical operations, such as

and some special enumerations, such as

SequencableCollection » *

For lists, there are more useful enumerations, such as

as well as other useful extensions, such as:

as well as more literal accessors, such as

and smart implementations of #copyFrom:to: that understand negative, as well as, out of range indices

Bag » *

And finally, there are some nice extensions for bags, such as


SequencableCollection » sliceFrom: start to: end

Answer a copy of the receiver, starting from the element at start index up to and including the element at end index. Other than #copyFrom:to:, this method does never raise a SubscriptOutOfBoundsError. Also, negative indices may be used to count indices from the collection's end rather than start.

The method is implemented as follows

``` SequeancableCollection >> sliceFrom: s to: e | start end | start := 1 max: (s positive ifTrue: \[s] ifFalse: \[self size + s + 1]). end := self size min: (e positive ifTrue: \[e] ifFalse: \[self size + e]). ((start > end) or: \[end

For convenience, we provide #sliceFrom: and #sliceTo: as well.


Filename » *

There are some nice accessors and enumerations for filenames, either recursive or not