CSE 341 - Homework 4 - Smalltalk Warmup

Due: Nov 14, 10pm (due date extended!)

  1. Define a class Stack, as described in the lecture notes. To make it easy to submit the answer to this question, define a new class category named Stacks in a browser, and define your class Stack in that category.

    Test your class by opening a workspace, making a couple of instances of Stack, and sending each of them some push: and pop messages. Open an inspector on each stack so you can see its state.

    Once you have the stack working, add three more methods:

  2. Now put some test cases in a more permanent place than a workspace, by defining a method test for Stack that runs some suitable tests, printing the results to the transcript. Your test method should create and exercise at least two separate, independent stacks.

    Hint: open a transcript using the "open ..." menu item, then picking "transcript". Here is some code that exercises a stack. (Be sure and open the transcript before running this, so that the results show up. You need the final Transcript flush to get the characters to show -- otherwise they may just be buffered up.)

        | s |
    s := Stack new setsize: 10.
    s push: 'squid'.
    s printOn: Transcript.  Transcript cr.
    s pushAll: #('fee' 'fie' 'fo' 'fum').
    s printOn: Transcript.  Transcript cr.
    Transcript flush.
    

  3. Now define a subclass of your Stack, called FilteredStack, that has two methods: setsize:filter: and push:. The setsize:filter: method takes two parameters: the initial size of the stack (as with the class Stack), and a block for the filter. The block should take one argument and return true or false. The push: method should check whether the filter returns true when applied to the argument; if so, it should be pushed onto the stack. For example, after executing the following positives should just contain 10 (the 0 and -3 get discarded).
       | positives |
    positives := FilteredStack new setsize: 10 filter: [:x | x>0].
    positives push: 10.
    positives push: 0.
    positives push: -3.
    
    Or as another example, after executing this code the stack should just hold 'clam' and 'squid'.
       | fishfree |
    fishfree := FilteredStack new 
        setsize: 10 
        filter: [:x | (x includesSubString: 'fish') not].
    
    fishfree pushAll: #('one fish' 'two fish' 'clam' 
    'red fish' 'blue fish' 'squid').
    

    Define another test method for FilteredStack that demonstrates that it works correctly as well. Your test method should create at least two stacks, with different filters.

    For full credit, your FilteredStack class may not directly reference Stack's instance variables (top and store). Instead, it must only send messages to self or super to access the stack's state (stored in top and store). Further, FilteredStack can only define the two methods setsize:filter: and push:. However, FilteredStack should have its own instance variable to hold the block (called say filter).

    The idea with these restrictions on what gets full credit is first, that the code will be written in better style; and second, you will use self and super, and understand how they work. For example, the push: method in FilteredStack should use super to get at the push: method inherited from Stack. And pushAll:, inherited from Stack, should still end up invoking the version of push: redefined in FilteredStack.

    To create the file for the electronic submission for your answer to Questions 1 and 2, select the class category Stacks in a browser and then pick 'fileOut' from the "yellow button" menu (right hand button on Windows, or option-click on a Mac).

  4. Browse to the spiral:angle: method in the Pen class, and try executing the code in the comment:
    Display restoreAfter: [
    Display fillWhite. Pen new spiral: 200 angle: 89; home; spiral: 200 angle: -89].
    
    This version of spiral is arguably a bit over the top with the multiple colors. Define a new method category in Pen named 341-spirals In this category, define a new method simpleSpiral:angle: in Pen that just draws with the current color of the Pen (which defaults to black). (You can change the start and step values in the loop if you want.)

    Using simpleSpiral:angle:, define a new method manySpirals, also in the 341-spirals category, that displays a spiral at the current mouse position whenever the user clicks the mouse. The method should keep looping and drawing spirals until the user clicks using the "yellow button" (right-hand button on windows, option-click on a Mac). You decide how to pick the exact angle, size, and color for each spiral -- for example, you could make them all be the same, you could cycle among some possibilities, or choose randomly. (Any of these possibilities will receive full credit.)

    Hints: Look at the method Pen>geometric designs>web in the class Pen for an example of a method that has this same pattern of waiting for a mouse click and drawing a pattern at the current position. If you want to use random numbers, to generate a random number, make a new generator by evaluating Random new. Each time you send next to the generator, you get a new random number between 0 and 1.

    To create the file to submit for your answer to this question, select the method category 341-spirals in a browser and pick 'fileOut' from the yellow-button menu, as for the first two questions.

  5. Extra credit (10% max extra): enhance your manySpirals method in some interesting and creative way, for example, by playing sounds, using animation, or whatever.