One thing I have often seen and lamented is students writing excessively complicated code with way too many classes. There is a huge difference between "A Robot knows its position and direction." and "A Robot has-a Position and has-a Direction." The first is the important one. The second is an over-commitment to too many classses. For a problem like this, you really really do not want a Direction class, and you certainly have no use for double dispatch. A position can be represented by a pair of integers x, y. It could also be represented by a Point with integer components. A direction could be represented by a pair of integers dx, dy such that |dx|+|dy| = 1. It could also be represented by a Point with integer components. For movement, you need to be able to add the direction to the location, which could be simply x := x + dx. y := y + dy. or it could be position := position + direction. For turning, you need to be able to rotate a direction vector by ninety degrees. Now it so happens that Point has methods #leftRotated and #rightRotated. So we can do the following: a Robot has position (a Point) and direction (aPoint) position := 0 @ 0. direction := 0 @ 1. To move forward without turning: position := position + direction. To turn left without moving: direction := direction leftRotated. To turn right without moving: direction := direction rightRotated. To obey a sequence of characters, commands: commands do: [:each | each caseOf: { [$A] -> [--move forward--]. [$L] -> [--turn left--]. [$R] -> [--turn right--] }]. One of the key ideas in extreme programming is "You Ain't Gonna Need It", abbreviated to YAGNI! The idea is *DON'T* generalise beyond your immediate needs. In this case, for example, the likelihood of *this* program needing to deal with more general kinds of movement is ZERO. And the only reason for using Point here instead of just using a few simple assignment statements is that Point already exists, so costs nothing to write, and as a familiar class, code using it should be easy to read. If someone challenges you to do something counter-productive, refuse the challenge. On Mon, 8 Apr 2019 at 17:21, Roelof Wobben <r.wobben@home.nl> wrote:
I can try to explain what I trying to solve.
I have a Robot which can turn left, turn right or moveForward.
now I have a string like 'LAR'
that means the robot needs to turn left (l) , move forward one place (A) and turn left. and I have to keep track to which direction the robot is facing and on which coordinate it stands.
so to summarize with the above string
lets say the robot is facing north on coordinate (0,0) then it has to turn left , so its facing east and still on coordinate (0,0) then it has to move forward, so its still facing east but are on coordinate(0,1) then it has to turn right, so its facing north and on coordinate (0,1)
and TimMacKinnon has challenged me to do this with double dispatch.
So I think now I need a object Direction, a sub object North and a sub - sub object TurnLeft, turnRight and moveForward.
So I can use double dispath first the direction North, East, South, West and then use double dispatch to find the right move.
Roelof
Op 8-4-2019 om 06:50 schreef Richard O'Keefe:
It would really REALLY **REALLY** help if we knew what the heck you were trying to do. There is an excellent chance that it is MUCH simpler than you think. If you cannot show us the Smalltalk version of the problem, can you show us the version for some other language?
On Sun, 7 Apr 2019 at 20:15, Roelof Wobben <r.wobben@home.nl> wrote:
Op 6-4-2019 om 15:15 schreef K K Subbu:
On 06/04/19 4:49 PM, Roelof Wobben wrote:
Hello,
I just learned double dispatch. And now for the Robot challenge of exercism Tim has pointed me to this article( https://blog.metaobject.com/2019/04/accessors-have-message-obsession.html)
but I fail to see how the move method looks like in that article. I had a conversation with Tim in the exercism channel and the way he explains it, it looks like double dispatch for me.
Am I on the right track or do I oversee something here.
unary methods like moveRight perform specific ops and are not parametric, so only a single dispatch, depending on the receiver, is needed.
If you change it to move: aDistanceOrAngle, then performing requests like "move: 3 cms" or "move: 30 degrees" will depend not only on the receiver but also on the class of the argument. This would need double dispatch (aka multiple polymorphism). The first dispatch would be based on the receiver and the receiver's method would then dispatch it based on the class of the argument (i.e. Distance>>move or Angle>>move )
HTH .. Subbu
hmm, still stuck
I have now a class Direction with as instance variables north, south, east, west and made the accessors.
then I thought I need a initialize like this :
initialize north = Direction( 0, -1). east = Direction( 1, 0). south = Direction( 0, 1). west = Direction(-1, 0).
but the Direction (0,-1) is a problem . the compiler does not like the (0,-1) part
to give you the big picture. I have a Robot which can turnRight , turnLeft and moveForward and I try to understand how the page would work in my case.
So I have a object Direction as described above and a Object MoveForward which is a subobject of Direction. MoveForward has only 1 method :
IsMove ^ 'A'
Roelof