views:

907

answers:

4

A class I am taking currently requires us to do all of our coding in smalltalk (it's a Design class). On one of our projects, I am looking to do some things, and am having a tough time finding how to do them. It seems that what most people do is modify their own version of smalltalk to do what they need it to do. I am not at liberty to do this, as this would cause an error on my prof's computer when he doesn't have the same built-in methods I do.

Here's what I'm looking to do:

Random Numbers. I need to create a random number between 1 and 1000. Right now I'm faking it by doing

rand := Random new.
rand := (rand nextValue) * 1000.
rand := rand asInteger.

This gives me a number between 0 and 1000. Is there a way to do this in one command? similar to

Random between: 0 and: 1000

And/Or statements. This one bugs the living daylights out of me. I have tried several different configurations of

(statement) and: (statement) ifTrue...
(statement) and (statement) ifTrue...

So I'm faking it with nested ifTrue statements:

(statement) ifTrue:[
    (statement) ifTrue:[...

What is the correct way to do and/or and Random in smalltalk?

+5  A: 

The problem is that

 (expr) and: (expr) ifTrue: aBlock

is parsed as the method and:ifTrue: If you look at the Boolean class (and either True or False in particular), you notice that ifTrue: is just a regular method, and that no method and:ifTrue: exists - however, plain and: does. So to make it clear that these are two messages, write

((expr) and: (expr)) ifTrue: aBlock

For longer boolean combinations, notice that there are also methods and:and: and and:and:and: implemented.

Martin v. Löwis
awesome, that solves one of them
contagious
But that's incomplete since and: takes a block, as said by rydier. And and without the column would be parsed as a unary message and cause a parse error afterwards because it only expects messages after it, not a full expression.
Damien Pollet
+4  A: 

As for the Random issue: it depends on what ST version you use. In Squeak 3.9, there is Random>>#nextInt:, which is documented as "Answer a random integer in the interval [1, anInteger].". Its implementation reads

(self next * anInteger) truncated + 1

So I have two comments here:

  1. You should really learn to use the class browser. This can answer the (frequent) questions "what messages can I send to objects of class X"
  2. It is common, in ST, to add new methods to existing classes. So if you want Random to have between:and:, just add it, e.g. as

    between: low and: high      
       ^(self next * (high-low+1)) truncated + low
    
Martin v. Löwis
well, thats the thing. We're not using Squeak at all. The version we're using only has next and nextValue.
contagious
Still, you can add any new methods that you find useful.
Martin v. Löwis
The mechanism Martin is referring to is named class extensions. Basically you can define a method on a class that was defined elsewhere, and still have that method packaged with the rest of your code, be it in a fileout or a commit. The way to do it exactly depends on the dialect, but you still haven't told us which one you're using...
Damien Pollet
+2  A: 

If you're using VisualWorks, and: takes a block as an argument, so you'd write:
(aBoolean and: [anotherBoolean]) ifTrue: [doSomething].
There's also &, which does not take a block as argument,
aBoolean & anotherBoolean ifTrue:[doSomething].
The difference is and: only evaluates what's in the block if the first bool is true (similar to java), while & always evaluates both.
Thus and: comes in handy if the second condition is computationally expensive, or if it includes state alterations which should only happen when the first condition is true. (that's usually a bad design though).

As for the Random, as long as you deliver your custom method, Random >> between:and: as well as the rest of your code, it runs fine on your professors computer. How to do that specifically, depends on the format in which you are supposed to deliver the assignment.

Rydier
+1  A: 
(1 to: 1000) atRandom