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 >> <b>asSortBlock</b>
    ^\[ :<!-- -->a :<!-- -->b | (a perform: self) <= (b perform: self) ]
 BlockClosure >> <b>asSortBlock</b>
    self numArgs = 1 ifTrue: \[ ^\[ :<!-- -->a :<!-- -->b | (self value: a) <= (self value: b) ] ].
    self numArgs = 2 ifTrue: \[ ^self ].
    self error: 'Not a sort block.' 

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

  • assert
  • cull: arguments
  • haltIfTrue
  • millisecondsToRun
  • profile

Character » isSpace

Answer whether the receiver is a space.

CharacterArray » *

Useful extensions of strings includes

  • asCapitalized
  • asPlural
  • lastWord
  • lines
  • linesDo: aBlock
  • piecesCutWhereCamelCase
  • trimQuotes
  • trimSeparators
  • withIndefiniteArticle

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

  • endsWith: aString
  • removeSuffix: aString
  • removePrefix: aString
  • replaceSuffix: aString with: newSuffix
  • startsWith: aString

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 >> <b>transitiveClosure:</b> unaryBlock
    ^self species withAll: (self asSet <b>transitiveClosure:</b> unaryBlock)
  Set >> <b>transitiveClosure:</b> 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 >> <b>removeAny</b>
    ^self remove: self any

* » asCollectionDo: aBlock

General purpose implementation of #do:, implemented as

  UndefinedObject >> <b>asCollectionDo:</b> aBlock
    ^self
  Object >> <b>asCollectionDo:</b> aBlock
    aBlock value: self
  Collection >> <b>asCollectionDo:</b> aBlock
    self do: aBlock
  CharacterArray >> <b>asCollectionDo:</b> 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 >> <b>asCollection</b>
    ^#()
  Object >> <b>asCollection</b>
    ^Array with: self
  Collection >> <b>asCollection</b>
    ^self
  CharacterArray >> <b>asCollection</b>
    ^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,

  • cartesianProduct: aCollection
  • difference: aCollection
  • intersection: aCollection
  • union: aCollection
  • aCollection , same as #difference:

mathematical operations, such as

  • average
  • average: aBlock
  • detectHighest: sortBlock
  • detectLowest: sortBlock
  • detectMax: aBlock
  • detectMin: aBlock
  • deviation
  • maxValue: aBlock
  • minValue: aBlock
  • normalized
  • sum
  • sum: aBlock

and some special enumerations, such as

  • collectUnion: aBlock
  • count: aBlock
  • countNot: aBlock
  • cross: aCollection do: binaryBlock

SequencableCollection » *

For lists, there are more useful enumerations, such as

  • affect: aBlock
  • crossDo: binaryBlock
  • pairsDo: binaryBlock
  • triangleDiagonalDo: binaryBlock
  • triangleDo: binaryBlock
  • with: aCollection collect: binaryBlock

as well as other useful extensions, such as:

  • evenElements
  • findFirst: aBlock ifAbsent: exceptionBlock
  • findLast: aBlock ifAbsent: exceptionBlock
  • indicesOf: anElement
  • oddElements
  • reverseSort: sortBlock
  • shuffle
  • sortReverse: sortBlock, same as above

as well as more literal accessors, such as

  • second
  • third

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

  • sliceFrom: start to: end
  • sliceFrom: start
  • sliceTo: end

Bag » *

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

  • associations
  • maxOccurrences
  • mostOccurring
  • sortedCounts

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 >> <b>sliceFrom:</b> s <b>to:</b> 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 <= 0]) ifTrue: \[^self copyEmpty: 0].
    ^self copyFrom: start to: end

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


Filename » *

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

  • allFiles
  • allFilesDo: aBlock
  • files
  • filesDo: aBlock
Last changed by admin on 21 April 2009