Table of Contents

This document implements fizzbuzz in smalltalk. It was created as part of an application for the Recurse Center.

Write a program that prints out the numbers 1 to 100 (inclusive). If the number is divisible by 3, print Crackle instead of the number. If it's divisible by 5, print Pop. If it's divisible by both 3 and 5, print CracklePop. You can use any language.

Extending class Integer

The GNU-Smalltalk Tutorial has an example where Number is extended to calculate the radius and circumference of circles. It formed the basis for my approach here. In part because it expresses the way Smalltalk can be used and takes me out of my comfort zone.

Number extend [
    radiusToArea [
        ^self squared * Float pi
    ]
    radiusToCircumference [
        ^self * 2 * Float pi
    ]
]

C-like fall through

I started out trying to find a switch/case/cond control structure. When Googling produced some exotic approaches via StackOverflow, I reckoned I might be swimming against a tide.

Early attempts at this implementation ran into the difficulty of not printing the default case when something else matches. The solution to use ^nil suggests how ugly this approach is.

Integer extend [
    fb [
        (self \\ 15 = 0)
            ifTrue: ['fizzbuzz' printNl.
                     ^nil].
        (self \\ 3 = 0)
            ifTrue: ['buzz' printNl.
                     ^nil].
        (self \\ 5 = 0)
            ifTrue: ['fizz' printNl.
                     ^nil].
        self printNl.
        ^nil.
    ]
]

As a Decision Tree

Since Smalltalk does not have an equivalent to switch or case or Lisp's cond. This probably reflects the fact that each message to which an object responds must be explicitly defined and switch/case/cond is designed to accept an arbitrary number of arguments. While it might be possible to generate a set of messages that cover many likely arities Object would receive, it probably is not worth building into the base language.

This is the source for fizzbuzz.st:

Integer extend [
    fizzbuzz [ 
        (self \\ 15 = 0)
        ifTrue: ['fizzbuzz' printNl]
        ifFalse: [
             (self \\ 3 = 0)
             ifTrue: ['fizz' printNl]
             ifFalse: [
                  (self \\ 5 = 0)
                  ifTrue: ['buzz' printNl]
                  ifFalse: [self printNl]
             ]
        ]
    ]
]

<<loop-over-interval>>

Smalltalk Notes

Printing Strings

Most Smalltalk tutorials begin with something like:

'Hello World' printNl
" -> 'Hello World' "

The subtilty this glosses over is that most of the time when using strings, people don't want the string's Object represention with the quotation marks. They want Hello World not 'Hello World'. Smalltalk being Smalltalk, it is certainly possible to redefine the message printNl for String. But there is a built in alternative displayNl that strips off the quotation marks.

Working with directories in the REPL

The gst REPL can be used for regular systems programming. The Directory object will provide the current working directory using the message Directory working. It will allow changing the working directory using the message Directory working: 'some-directory'.

Crackle Pop

Extend Integer

The source for cracklePop.st:

"cracklePop.st

Print out the numbers 1 to 100 (inclusive). 
  + If the number is divisible by 3, print Crackle instead of the number. 
  + If it's divisible by 5, print Pop. 
  + If it's divisible by both 3 and 5, print CracklePop.

To load the program use: 
  FileStream fileIn: 'cracklePop.st'
"

Integer extend [
    cracklePop [
        (self \\ 15 = 0)
        ifTrue: ['CracklePop' displayNl]
        ifFalse: [
            (self \\ 3 = 0)
                ifTrue: ['Crackle' displayNl]
                ifFalse: [
                    (self \\ 5 = 0)
                        ifTrue:['Pop' displayNl]
                        ifFalse: [self displayNl]
                ]
        ]
    ]
]
<<loop-over-interval>>

Loop over the interval

By looping standards, iterating over an index in Smalltalk at first feels a bit indirect uses the Interval object. But after thinking about it a bit, I realized that this is sort of prelude to some languages' generator syntax (even if it is not lazy).

It also feels a bit verbose, but after realizing it replaces symbols with letters composing words, it probably is about the same number of characters and closer to ordinary English. Not trying to conform to the structure of Algol and Fortran and C is one of the things I have really started to appreciate about Smalltalk.

1 to: 100 by: 1 do: [:i | i cracklePop]

Author: benrudgers

Created: 2017-05-05 Fri 21:55

Validate