The Lambda Lounge is having a language shootout this Thursday at it's monthly meeting. Basically many people are going to implement a vending machine each in a different language and then we'll compare. There are many languages that are going to be represented, Ruby, Groovy, Fan, Erlang and Haskell to name a few. The spec can be found here. The objective is to implement a basic vending machine, that can vend things such as a candy bar, soda, chips, etc. It also needs to keep track of the state of the vending machine, such as how much cash it has, whether it can make change and so on. I think that it's a good problem, requires some thought and effort, but not too tough. I caught myself a few times wanting to get carried away, so you could definitely take it to the extreme in terms of complexity.
The Squeak Vending Machine
I implemented the vending machine using Squeak. The most interesting thing about this implementation is that it doesn't rely on any external input. There is no prompt for a string of input, which would then be parsed/interpreted and converted to some running state. Instead everything is implemented inside of the Smalltalk language. Below is an example from one of the tests discussed in the specification:
vendingMachine := VendingMachine new. result := vendingMachine Q Q Q Q GETB. self should: result item name = 'Chips'. self should: result moneyBack total = 0.0.
This is a snippet from an SUnit test. The purpose of the test is to ensure that the item is vended and appropriate change is given. It also checks to make sure the vending machine has the appropriate amount of money afterwards, but I removed that from the example to make it more clear. The first line just instantiates a new vending machine (this is actually done in the setUp method of the unit test). The vending machine is initialized using a default set of items and change pre-loaded. The next line is a little more complex. := is just the assignment operator. The right side calls a method on vendingMachine. Actually it's calling "Q Q Q Q GETB" on vendingMachine. On the back end, this is incrementing the quarters in the vending machine by 1, 4 times. Then it calls the GETB method. This triggers the vending mechanism to vend the result. That line is 5 method calls total. The next two lines check that the result is in fact a bag of chips and there is no change returned. The interesting thing here, is that the actual code to interact with the vending machine (what the "user" would type) is "vendingMachine Q Q Q Q GETB". This is valid Smalltalk and can be executed directly.
Running the Code
If you're interested in running the code, it can be downloaded here. You're welcome to look at the st files via a text editor, but that's not the intention. In Squeak, everything exists inside the VM. I think of the Squeak VM as more like a hardware virtualizing product (Xen, Virtualbox etc) and less like the JVM. Everything existing inside the VM means even the source files are in the VM image. So I didn't just go to the directory that I've been working in and copy the st files, I actually had to "export" or as it's called in Squeak, "file out" the code. This code is then ready to be "filed in" or "installed" into another running Squeak VM. When you're working in Squeak, you don't really worry about which file is where. For that reason, traditional version control software doesn't integrate well with Squeak. I think there have been some recent projects to get Squeak to work with Subversion, but I have not used those libraries. For version control, most Squeak developers use Monticello as far as I know. It's a source control repository written specifically for Smalltalk. I have used it before, but I don't have my own repository set up.
To install and run the vending machine in Squeak, download and install Squeak per the instructions here. Then start Squeak by running the squeak executable (depends on the platform, in Linux it's just squeak). Then follow the below instructions:
- Download the attached squeak_vendingmachine_source.zip
- Unzip the source anywhere you'd like, there should be 2 st files and a readme.txt
- In the running Squeak window, left click on the background and then click open
- Click file list and navigate to where the files were unzipped
- Select the Vend.st file and then at the top of the window, click install
- Do the same for VendTests.st
- Left click on the background again and again click open
- About 3/4 of the way down the menu, click Test Runner
- Navigate down to the bottom of the test package list and select VendTests
- On the right, select any or all three of the test classes and at the bottom left, click Run Selected
- Green bars should be visible, showing that the tests passed
If you want to look at the source, you can left click on the background, select open, then class browser. In the far left pane at the top, if you scroll to the bottom, there are two packages, Vend and VendTests with the source code.