Thanks,
for the discusson and lessons.
I will think about it and also think if smalltalk is for me.
I did the pharo Mooc and still have a lot of problems making the smalltalk way click in my head so I can solve little problems like this.
Out of coriousy what dialect do you use?
Op 8-4-2019 om 17:11 schreef Richard O'Keefe:
You are expected to use my code fragments for *ideas*,not to incorporate them *literally* in your code. AsI explained, *without seeing the specification*, I haveno way to tell whether the specification uses a left-handedor right-handed coordinate system.
For what it's worth, here's a complete program in mySmalltalk dialect. It doesn't plug into the exercismtesting framework because I can do not know what itlooks like. But if it makes the code more complicatedthat this, it's doing it wrong.
require: 'geometry.st' "Point"
require: 'print.st' "OutputStream>>print:"
Object subclass: #Robot
instanceVariableNames: 'position direction'
poolDirectionaries: 'FileStream'
methods for: 'initialising'
pvtPostNew
position := 0@0.
direction := 1@0.
methods for: 'accessing'
direction
^direction copy
location
^location copy
obey: commands
commands do: [:each |
each caseOf: {
[$A] -> [position := position + direction].
[$L] -> [direction := direction leftRotated].
[$R] -> [direction := direction rightRotated]
}].
class methods for: 'main'
start
[StdIn atEnd] whileFalse: [
|robot|
robot := Robot new.
Robot obey: StdIn nextLine.
StdOut print: Robot location; cr].
On Tue, 9 Apr 2019 at 02:58, Roelof Wobben <[hidden email]> wrote:
yes, this is a real tests from the pharo track on exercism.io
I understand what you mean but maybe I overthinking things.
But if we have a robot facing north and the robot turns to the left , im my oponion it faces now to the east.
like this test is saying :
test04_RotatesTheRobotsDirection90DegreesClockwiseChangesTheDirectionFromEastToSouth
| result |
result := robotSimulatorCalculator
moveDirection: 'east'
position:
(Dictionary new
add: 'x' -> 0;
add: 'y' -> 0;
yourself)
instructions: 'R'.
self
assert: result
equals:
(Dictionary new
add: 'direction' -> 'south';
add:
'position'
->
(Dictionary new
add: 'x' -> 0;
add: 'y' -> 0;
yourself);
yourself)
but I cannot come to the same outcome with this code :
pointToName: aPoint^aPoint x isZeroifTrue: [aPoint y > 0 ifTrue: [#north] ifFalse: [#south]]ifFalse: [aPoint x > 0 ifTrue: [#west ] ifFalse: [#east ]]
maybe exercism.io is not a good way to practice and learn smalltalk but I found not a better one. or smalltalk is not for me.
Roelof
Op 8-4-2019 om 16:44 schreef Richard O'Keefe:
The basic issue here is abstraction.An instance of "Robot" in your program is not aphysical object. How could it possibly point North,South, or Nor-nor-west? It cannot.Its location and direction are abstract values*metaphorically* related to real world notionslike position vectors and velocity vectors."North" in this program is not a real thing,it is an *idea* which could be represented by'North', 'north', #North, #north, $N, $n,'Raki', 'raki', #Raki, #raki, $R, $r,137, (0@ -1), a picture of the star Polaris,the colour red (the conventional colour forthat end of a compass needle which points north),a sound recording of a lecture by Alfred NorthWhitehead, or anything you please, as long as,inside the program, it *acts* the way *you* want"north" to act (which is not necessarily the waythe physical direction North acts, and in fact inthis case it most certainly is not).
Locations and movements in a 2D space are, in Smalltalk,commonly represented by Points. "Represented by."
As for this method:
test11_MovesTheRobotForward1SpaceInTheDirectionItIsPointingIncreasesTheYCoordinateOneWhenFacingNorth
| result |
result := robotSimulatorCalculator
moveDirection: 'north'
position:
(Dictionary new
add: 'x' -> 0;
add: 'y' -> 0;
yourself)
instructions: 'A'.
self
assert: result
equals:
(Dictionary new
add: 'direction' -> 'north';
add:
'position'
->
(Dictionary new
add: 'x' -> 0;
add: 'y' -> 1;
yourself);
yourself)
PLEASE tell me that is not what they are actually using.Let's start with(Dictionary new)add: k1 -> v1;...add: kn -> vn;yourselfDid you know that sending #add: to a dictionary is notportable? Storing actual Association objects insideDictionaries was originally an encapsulation error andremains a performance error, so there are Smalltalksthat do not make that mistake. The *portable* way tomake a Dictionary is(Dictionary new)at: k1 put: v1;...at: kn put: vn;yourself.
And why in the name of sanity are the keys *strings*instead of *symbols*? This is not Smalltalk. It isJavascript in drag.
Now exercism.io has a habit of insisting on particularimplementations. For example, I completed the SML track,and found that the test code ONLY worked with Poly andnot with any of the three SML implementations I alreadyhad on my machine. Since you are doing this in Pharo,I take it that exercism.io will insist on the Smalltalktrack being done in Pharo, and in that case it is*nauseating* to use a Dictionary when you could use aPoint. Old-fashioned Smalltalk style would have beento return something like#(<direction> <x> <y>)e.g. #(north 1 0), and I still prefer that.
In fact *good* Smalltalk style for something like thiswould betest11_MovesTheRobotForward1SpaceInTheDirectionItIsPointingIncreasesTheYCoordinateOneWhenFacingNorth
robotSimulatorCalculatormoveTo: 0@0;
head: #north;
obey: 'A'.self assert: robotSimulatorCalculator heading equals: #north.self assert: robotSimulatorCalculator location equals: 0@1.
-- We're starting to get the idea that identifiers likerobotSimulatorCalculator are not a very good idea whensimulatedRobot would do the job as well or better.
(This is also pointing us towards Betrand Meyer'sCommand/Query Separation principle, but we shan'tgo there today.)
This is important feedback to give to the exercism.iopeople. The test code should use a SMALLTALK interface,not a warmed-over JAVASCRIPT interface.
Now, how do we map between direction *names* anddirection *points*? Well, we have to start bylaying down clearly what we *mean* by the directions.
To move North one step is to add 1 to y and 0 to x.(We know that from the appalling test case above.)
To move South one step is to add -1 to y and 0 to x.(South is the opposite of North.)
To move East one step, oh we have a problem.THIS NEEDS SPELLING OUT. And one of the things theexercism.io exercises are HORRIBLY BAD AT is specifyingthe problem. Nearly every single exercise I have tried,I have been unable to tell what the problem is withoutexamining the test cases, and that is not the wayexercises are supposed to work. (Yeah, that's why I'mscreaming about it. I've taught a class using exerciseslike this that were not of my writing and vague specificationsreally upset the students. People who had taken the classunder someone else several years before were still angryabout it.)
The geometric classes in Smalltalk were written to supportgraphic user interfaces. And in user interfaces, the ycoordinate increases DOWN. So if we take the compass roseand rotate it so that North is DOWN, it follows thatWest is right and East is left. So
To move East one step is to add -1 to x and 0 to y.To move West one step is to add 1 to x and 0 to y.
The chances are excellent that the problem specificationis inconsistent with this. Sigh. Let's proceed, though.
North 0@1South 0@ -1East -1@0West 1@0
pointToName: aPoint^aPoint x isZeroifTrue: [aPoint y > 0 ifTrue: [#north] ifFalse: [#south]]ifFalse: [aPoint x > 0 ifTrue: [#west ] ifFalse: [#east ]]
nameToPoint: aSymbolaSymbol = #north ifTrue: [^0 @ 1].aSymbol = #south ifTrue: [^0 @ -1].aSymbol = #west ifTrue: [^1 @ 0].aSymbol = #east ifTrue: [^-1 @ 0].aSymbol error: 'not a compass direction in lower case'.
Another problem I had with exercism was a "Space-Age"exercise where the README.md capitalised the planet namesbut test_Space-Age.<whatever> insisted on lower case.That might well happen here.
Just for grins,Dictionary>>asPoint^(self at: 'x') @ (self at: 'y')
Point>>asDictionary^(Dictionary new)at: 'x' put: self x;at: 'y' put: self y;yourself
On Mon, 8 Apr 2019 at 22:15, Roelof Wobben <[hidden email]> wrote:
Richard thanks.
One thing I do not see direct.
you said :
A direction could be represented by a pair of integersdx, dy such that |dx|+|dy| = 1. It could also berepresented by a Point with integer components.
for me a direction is the direction the robot is facing so something like north or east.
the challenge also wants a output like this :
test11_MovesTheRobotForward1SpaceInTheDirectionItIsPointingIncreasesTheYCoordinateOneWhenFacingNorth
| result |
result := robotSimulatorCalculator
moveDirection: 'north'
position:
(Dictionary new
add: 'x' -> 0;
add: 'y' -> 0;
yourself)
instructions: 'A'.
self
assert: result
equals:
(Dictionary new
add: 'direction' -> 'north';
add:
'position'
->
(Dictionary new
add: 'x' -> 0;
add: 'y' -> 1;
yourself);
yourself)
so how do I "convert" the point you are using to the text.
Or do I misunderstood you somewhere wrong.
Roelof
Op 8-4-2019 om 10:57 schreef Richard O'Keefe:
One thing I have often seen and lamented is studentswriting excessively complicated code with way too manyclasses. 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 isan over-commitment to too many classses. For aproblem like this, you really really do not wanta Direction class, and you certainly have no usefor double dispatch.
A position can be represented by a pair of integersx, y. It could also be represented by a Point withinteger components.
A direction could be represented by a pair of integersdx, dy such that |dx|+|dy| = 1. It could also berepresented by a Point with integer components.
For movement, you need to be able to add the directionto the location, which could be simplyx := x + dx. y := y + dy.or it could beposition := position + direction.For turning, you need to be able to rotate a directionvector by ninety degrees. Now it so happens thatPoint 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 immediateneeds. In this case, for example, the likelihood of*this* program needing to deal with more generalkinds of movement is ZERO. And the only reason forusing Point here instead of just using a few simpleassignment 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 <[hidden email]> 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 whatthe heck you were trying to do. There is an excellentchance that it is MUCH simpler than you think. If youcannot 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 <[hidden email]> 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
Free forum by Nabble | Edit this page |