real language

Bookmarking Digg Diigo DZone Earthlink Google
Windows Live LookLater Ma.gnolia Reddit Rojo StumbleUpon Technorati

Language Smalltalk

(OO/humor version for gst)

Author:Paul H. Hargrove
Score: (3.00 in 28 votes)
" OO version for Smalltalk "
" Paul H. Hargrove 2007.06.10 "
" "
" Some people claim Smalltalk allows one to take OO to ridiculous extremes. "
" This program attempts to demonstrate that (with suitable self-ridicule). "
" Excluding the comments, no method is longer than three 80-char lines. "
" For aggressive code reuse, no string literal appears more than once. "
" 99 bottles is the default, but other lengths can be specified at "
" object instantiation. "
" "
" Written for and tested w/ GNU Smalltalk 2.3.5 "

!Number methodsFor: 'drinking songs'!
    "String factory: turns bottle count into English"
    ^((self = 0) ifTrue: ['no more'] ifFalse: [self printString]),
     ' bottle', ((self = 1) ifTrue: [' '] ifFalse: ['s ']), 'of beer'.
! !
!String methodsFor: 'drinking songs'!
initialUpper |s|
    "String factory: generates a copy with an initial capital"
    ^(s := (String withAll: self)) at: 1 put: (s first asUppercase); yourself.
! !

"Objects of class BeerSong are songs.  Send asString to return the lyrics."
Object subclass: #BeerSong
    instanceVariableNames: 'lyrics sizeOfWall bottleCount bottleString'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'Drinking-Songs'
! !
!BeerSong class methodsFor: 'instantiation'!
    "new: with default song length of 99 bottles"
    ^self new: 99.
new: wallSizeInUnitsOfBottles
    ^super new initialize: wallSizeInUnitsOfBottles
! !
!BeerSong methodsFor: 'initialization'!
initialize: aNumber
    "We generate the lyrics lazily when you show: them"
    "So initially we just set the maximum and current counts"
    lyrics := WriteStream on: String new.
    sizeOfWall := aNumber.
    bottleCount := 0.
!BeerSong methodsFor: 'manipulating bottles'!
adjust: aNumber
    "Changes the bottleCount and updates bottleString to match"
    bottleString := (bottleCount := bottleCount + aNumber) asBottles.
    "Buy as much beer as will fit on my wall"
    "ToDo: could we buy 'splits' when sizeOfWall is non-integer?"
    "ToDo: if sizeOfWall < 0 do we sell beer?"
    self adjust: sizeOfWall truncated.
    "What inevitably happens when passing beer bottles among friends"
    self adjust: -1.
    "Who keeps beer on a wall?  Is the fridge full of snacks?"
    ^bottleString, ' on the wall'.
!BeerSong methodsFor: 'private utilities'!
    "Let's party, we'll need tunes and some brews"
    self purchase.
    "Breathe after each verse, to avoid passing out"
    lyrics nextPutAll: '.'; nl; nl.

!BeerSong methodsFor: 'singing verses'!
    "I'm still sober enough to capitalize"
    lyrics nextPutAll: self report initialUpper;
           nextPutAll: ', ', bottleString, '.'; nl.
    ^bottleCount >= 1.
    "Hey buddy, could you pass me a cold one?"
    lyrics nextPutAll: 'Take one down and pass it around, ';
           nextPutAll: self drinkOne report.
    self breathe.
    "Anybody sober enough to make it to the store and back?"
    lyrics nextPutAll: 'Go to the store and buy some more... ';
           nextPutAll: self report.
    self breathe.
    "The party's not over 'till the beer runs out"
    [self checkWall] whileTrue: [self takeDown].
    "The next one of these has got to be BYOB"
    self buyBeer drinkBeer buyBeer passOut.
    "We generate the lyrics only once and cache them"
    lyrics isEmpty ifTrue: [ self throwParty ].
    ^lyrics contents.
! !

"For a shorter song:  Transcript show: (BeerSong new: 2)!"

Transcript show: BeerSong new!

Download Source | Write Comment

Alternative Versions

Squeak, VisualWorksJim Freeman07/03/054
standard versionPatrick M. Ryan04/20/050


>>  Paul H. Hargrove said on 06/17/07 19:46:53

Paul H. Hargrove After submitting this I realized that I'd left a method "planParty" that had become unused after I'd made some revisions. I considered submitting an update, but decided to leave it because it is a good example of what happens in practice as one's designs evolve. So, let us call "planParty" a legacy interface :-).

>>  claus said on 12/23/08 18:14:08

claus Great version!

Shows off the feature of extending core classes. I like this version better than the block closure-using one. Reason for this being that it appeals more to common programming techniques (and my personal dislike of heavy block closure usage).

Download Source | Write Comment

Add Comment

Please provide a value for the fields Name, Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.

Please don't post large portions of code here! Use the form to submit new examples or updates instead!




Security Code: