On Dec 4, 2006, at 6:21 PM, Edwin Fine wrote:

> Pete Yandell wrote:
>>     # Turn to face the given point.
>>     def toward(pt)
>>       raise ArgumentError unless is_point?(pt)
>>       @heading = (atan2(pt.first - @xy.first, pt.last  - @xy.last) /
>> DEG) % 360
>>     end
>>
>
> What is the correct behavior if calling toward(pt) and @xy == pt. In
> this case, atan2 returns 0.0 (North in turtle). This means that  
> setting
> the turtle to point to where it already is makes it always face North,
> which seems wrong. I would think that this should be a no-op (heading
> does not change).
>
> irb(main):004:0> Math.atan2(0,0)
> => 0.0
>
> Try this test case.
>
>   def test_toward
>     east = [100, 0]
>     @turtle.face east
>     assert_equal(90, @turtle.heading.round)
>     assert_nothing_raised { @turtle.face [0, 0] }
>     assert_equal(90, @turtle.heading.round)
>   end

You bring up a good point here. Commanding the turtle to face the  
point where it's located is really an indeterminate operation. I  
think there are three reasonable responses to such a command:

1. Raise an error (because an indeterminate operation should be  
treated like 0/0).
2. Make it a no-op (as you suggest).
3. Accept the value returned by Math#atan2 (a show of faith in the C  
math library :).

Philosophically, I favor the first response because I think this  
situation would most likely arise from a programmer error. But it's  
not an error that's commonly made. Also, in implementations  
maintaining the turtle's location with floats, testing whether or not  
@xy is the same as the argument given to toward/face is rather  
expensive. So in practice, I take the lazy way out and go with the  
atan2 flow.

However, I would not fault an implementation that goes one of the  
other routes.

Regards, Morton