如何在Smalltalk中生成指定范围内的随机整数?

3
我目前正在学习的一门课要求我们用Smalltalk进行编码(这是一门设计课)。在我们的一个项目中,我想做一些事情,但是在如何实现它们的问题上碰到了一些困难。似乎大多数人都会修改自己的Smalltalk版本以满足他们的需求。但是我不能这样做,因为这将导致我的教授的计算机出现错误,因为他没有我所拥有的内置方法。

以下是我的需求:

随机数。我需要创建一个1到1000之间的随机数。目前我通过模拟来实现它:

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

这会给我一个介于0和1000之间的数字。有没有一种方法可以在一个命令中完成这个操作?类似于

Random between: 0 and: 1000

And/Or语句。这个让我很烦恼。我尝试了几种不同的配置

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

所以我使用嵌套的ifTrue语句来模拟它:

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

在Smalltalk中,如何正确地使用and/or和Random?


将这两个不同的问题分开成两个独立的页面会很有用。 - Euan M
6个回答

6

问题在于

 (expr) and: (expr) ifTrue: aBlock

被解析为方法and:ifTrue:。如果你查看Boolean类(尤其是True或False),你会注意到ifTrue:只是一个普通的方法,而没有and:ifTrue:这个方法 - 但是有普通的and:。因此,为了清楚起见,表明这是两条消息,请写成

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

对于更长的布尔组合,注意还有实现了and:and:和and:and:and:方法。


但这是不完整的,因为 as said by rydier,and: 需要一个 block。没有冒号的 and 将被解析为一条一元消息,并在之后导致解析错误,因为它只期望在其后面接收消息,而不是一个完整的表达式。 - Damien Pollet

6
(1 to: 1000) atRandom

5
如果您正在使用VisualWorks,并且 `and:` 以块作为参数,那么您应该写成:
(aBoolean and: [anotherBoolean]) ifTrue: [doSomething].

还有&,它不接受块作为参数。

aBoolean & anotherBoolean ifTrue:[doSomething].

区别在于: and:仅在第一个bool为true时评估块中的内容(类似于java),而&始终评估两者。
因此,如果第二个条件计算代价高昂,或者如果它包括状态改变,只有在第一个条件为真时才应该发生(虽然这通常是不好的设计),那么and:就非常方便。
至于Random,只要你提供自定义方法Random >> between: and:以及其余代码,在您教授的计算机上运行良好。如何具体实现取决于您需要交付作业的格式。

4
关于随机问题:这取决于您使用的ST版本。在Squeak 3.9中,有一个名为Random>>#nextInt:的方法,文档说明为“返回区间 [1,anInteger] 中的随机整数。”其实现如下:
(self next * anInteger) truncated + 1

我有两个评论:

  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
    

好的,这就是问题所在。我们根本没有使用Squeak。我们正在使用的版本只有next和nextValue。 - helloandre
仍然,您可以添加任何您认为有用的新方法。 - Martin v. Löwis
Martin所提到的机制被称为类扩展。基本上,您可以在已定义的类上定义一个方法,并仍将该方法与代码的其余部分打包在一起,无论是在文件输出还是提交中。具体操作方式取决于方言,但您仍然没有告诉我们您使用的是哪种方言... - Damien Pollet

0
简单来说,如果不了解Smalltalk方言,我只能给出一个一般性的答案。根据你提出的随机问题,是的,如果你的教授需要一个通用的答案,那么这是唯一的方法。
至于and/or语句的问题,
引用:
And/Or语句。这个问题让我非常困扰。我尝试了几种不同的配置。
(statement) and: (statement) ifTrue...
(statement) and (statement) ifTrue...

你想尝试的是:

(statement) and: [statement] ifTrue: [ ... ]

注意括号,and: 方法接受一个块作为参数。


0

创建几个1到1000之间的随机整数
首先创建一个随机数序列。只需执行一次即可。

然后通过从序列中取下一个数字来创建新的随机数。根据需要重复此过程。

aRandomSeries := Random new .
    "Seed a new series of random numbers"  

aRandomInt := aRandomSeries newInt: 1000 . 
    "generate a random integer between 0 and 1000"

anotherRandomInt := aRandomSeries newInt: 1000 .
    "generate another random integer between 0 and 1000"

逻辑运算

aBoolean 可以响应 and:or:。它们都需要 块参数

以下是它们的工作原理。

and: alternativeBlock
如果接收器为真,则回答 alternativeBlock 的值;否则不评估 alternativeBlock 并回答 false。

or: alternativeBlock
如果接收器为假,则回答 alternativeBlock 的值;否则不评估 alternativeBlock 并回答 true。

例如:
( 3 > 2 ) or: [ 3 < 4 ] ifTrue: [ ]
aBoolean and: [ anotherBoolean ] ifFalse: [ ]

然而,Squeak 和 Pharo Smalltalks 都可以接受括号 ( ) 中的参数。
Dolphin Smalltalk 则不行,并严格要求使用标准的 Smalltalk 语法来传递块参数。

其他相关方法:
& 是一个不需要方括号(即块)参数的AND运算符
| 是一个不需要方括号(即块)参数的OR运算符
&| 可以在 Amber、Cuis、Gnu、Pharo、Squeak、VisualAge 和 VisualWorks Smalltalks 中使用。

Squeak Smalltalk 还提供了:
and:and: }
and:and:and: } 这些接受多个块参数
and:and:and:and }

or:or: }
or:or:or: } 这些接受多个块参数
or:or:or:or: }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接