Random subclass: #BetterRandom instanceVariableNames: 'transformBlock ' classVariableNames: '' poolDictionaries: '' category: 'New-Random'! !BetterRandom methodsFor: 'accessing'! next "return the next random number, having transformed it by the block" ^transformBlock value: super next! ! !BetterRandom methodsFor: 'private'! initialize "emulate my super" self transformBlock: [:x | x]! transformBlock: aBlock "aBlock should be a one-argument block -- the argument is the 'raw' random number" transformBlock := aBlock! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! BetterRandom class instanceVariableNames: ''! !BetterRandom class methodsFor: 'examples'! exampleCollection1 "Interval as argument" "BetterRandom exampleCollection1" | rand | rand := BetterRandom fromCollection: (1 to: 13 by: 0.7). 10 timesRepeat: [Transcript show: rand next printString; cr]! exampleCollection2 "SequenceableCollection as argument" "BetterRandom exampleCollection2" | rand | rand := BetterRandom fromCollection: ColorValue constantNames. 10 timesRepeat: [Transcript show: rand next printString; cr]! exampleCollection3 "Set as argument" "BetterRandom exampleCollection3" | rand | rand := BetterRandom fromCollection: Object subclasses. 10 timesRepeat: [Transcript show: rand next printString; cr]! exampleFloat "BetterRandom exampleFloat" | rand | rand := BetterRandom floatBetween: 4 and: 13. 10 timesRepeat: [Transcript show: rand next printString; cr]! exampleInteger "BetterRandom exampleInteger" | rand | rand := BetterRandom integerBetween: 4 and: 13. 10 timesRepeat: [Transcript show: rand next printString; cr]! ! !BetterRandom class methodsFor: 'instance creation'! floatBetween: start and: stop | size | size := stop - start. size > 0 ifFalse: [^self error: 'non-positive range']. ^self fromBlock: [:x | x * size + start ]! fromBlock: aBlock "aBlock should be a one-argument block -- the argument is the 'raw' random number" ^self new transformBlock: aBlock! fromCollection: aCollection "Create an instance of me which will return a random element from the argument" | size aSequenceableCollection | aSequenceableCollection := aCollection isSequenceable ifFalse: [aCollection asOrderedCollection] ifTrue: [aCollection]. size := aSequenceableCollection size. size > 0 ifFalse: [^self error: 'Empty collection']. ^self fromBlock: [:x | | index | index := (x * size + 1) truncated. aSequenceableCollection at: index]! integerBetween: start and: stop | size | size := stop - start. size > 0 ifFalse: [^self error: 'non-positive range']. ^self fromBlock: [:x | (x * size + start) truncated]! new ^super new initialize! !