'whileTrue in a block closure Smalltalk?
Can you use a whileTrue: inside a block closure? I can't get it to work so I suspect not. Or I am doing something wrong.
map := #([1 1 1 1 1]
[1 0 0 0 1]
[1 0 1 0 1]
[1 0 0 0 1]
[1 1 1 1 1]).
posx := 1.
posy := 1.
t4 := CompositePart new.
rot := (Core.Double.Pi / 4).
perspective := Core.OrderedCollection new.
1 to: 60 do: [:i | perspective add: (rot + (i - 30) asRAD).
rot_i := perspective at: i.
x := posx.
y := posy.
gsin := (0.2 * (rot_i sin)).
gcos := (0.2 * (rot_i cos)).
t2 := true.
[t2 = true]
whileTrue: [
x := (x + gcos).
y := (y + gsin).
n := (n + 1).
mapCoord := map at: x rounded asInteger.
mapCoord := (mapCoord at: y rounded asInteger).
(mapCoord = 1)
ifTrue: [
h := 1/(0.2 * n).
t2 := false]].
t3 := (i @ h extent: 2 @ h ) asFiller.
t4 add: t3].
I would like to get everything inside the whileTrue block to repeat if mapCoord isn't equal to 1. But it doesnt, it just chugs along to the next iteration in the "do:" block. I suspect Im doing something wrong, but I can't figure it out.
Solution 1:[1]
This is what I see.
At every do:
iteration, both x
and y
are initialized to 1
and then, inside the whileTrue:
, to something between 0.8
and 1.2
. Thus, the first assignment of mapCoord
evaluates to #[1 1 1 1 1]
and the second to 1
because #[1 1 1 1 1] at: 1
is 1
. Thus, t2
becomes false
and the whileTrue:
exits.
More clearly
x := posx. "x = 1"
y := posy. "y = 1"
gsin := (0.2 * (rot_i sin)).
gcos := (0.2 * (rot_i cos)).
t2 := true.
[t2 = true]
whileTrue: [
x := (x + gcos). "0.8 <= x <= 1.2"
y := (y + gsin). "0.8 <= y <= 1.2"
n := (n + 1).
mapCoord := map at: x rounded asInteger. "mapCoord = #[1 1 1 1 1]
mapCoord := (mapCoord at: y rounded asInteger). "mapCoord = 1"
(mapCoord = 1)
ifTrue: [
h := 1/(0.2 * n).
t2 := false]]. "t2 = false"
Solution 2:[2]
Syntactically there's no reason that it shouldn't work and as you can run the code, the answer to your question is: Yes you can! If you think the while loop doesn't do what you expect, i suggest you don't "do it", but rather try the "debug it" command. That'll allow you to step through your code statement by statement. You can inspect all variables along the way and maybe find out what's wrong.
Some remarks about your code:
- you use x/y separately but you're actually talking about a
Point
, which has a x and y property. It also supports large parts of the number's protocol, which means you can send the messagerounded
to aPoint
, too. You can createPoint
objects via@
like:point := 4 @ 5
. Points also allow arithmetics likepoint * 4
orpoint + something
. rounded
returns anInteger
, so there's no need to explicitly convert it viaasInteger
.- you have a method
asRAD
but there's already a system methoddegreesToRadians
- you shouldn't number your variables. The decompiler does that because it doesn't know better, but if you don't know how to name your variables, at least name them after the type they have.
t4
could beaComposite
Solution 3:[3]
[:i| | eye x y gsin gcos coordinate notLessThanOne h |
" So I can see it too. Yes--A while loop inside a block is fine "
eye := perspective add: (rot + (i - 30) asRAD).
X := posx. " x = 1 "
y := posy. " y = 1 "
gsin := (0.2 * (eye sin)).
gcos := (0.2 * (eye cos)).
coordinate := notLessThanOne.
[ coordinate < 1 " op changed to < "
] whileFalse:
[x := (x + gcos). " 0.8 <= x <= 1.2 "
y := (y + gsin). " 0.8 <= y <= 1.2 "
n := (n + 1). " grows forever? "
coordinate := map at: x rounded." is #[1 1 1 1 1] "
coordinate := coordinate at: y rounded." is 1 "
].
h := 1/(0.2 * n).
parts add: (1@h extent: 2@h) asFiller
]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Karsten |
Solution 3 |