[racket] Plot is voracious

From: Neil Toronto (neil.toronto at gmail.com)
Date: Wed May 21 13:18:22 EDT 2014

Division by zero and other math domain errors, primarily. There are two 
good reasons to ignore these.

1. Plotting is for visualizing functions. Users shouldn't have to ensure 
to Plot that the function they're plotting is total when all they want 
is to *see* it, not use it for some critical calculation.

More concretely, raising all exceptions means that this:

   (plot3d (surface3d / -1 1 -1 1))

has to be this instead:

   (plot3d (surface3d
            (λ (x y) (with-handlers ([exn?  (λ (e) +nan.0)])
                       (/ x y)))
            -1 1 -1 1))

or it has to use an explicit domain test (i.e. test (= y 0)). That's a 
lot of work just to visualize the division function.

2. Plotting necessarily approximates. Plot's behavior should be as 
consistent as possible regardless of exactly how it approximates.

Currently, plotting the division function in any subdomain or with any 
sampling interval just works. Suppose Plot allowed errors to be raised. 
Then this would plot just fine:

   (plot3d (surface3d / -2 1 -2 1))

because sampling 41 points (the default) within [-2,1] skips over 0. But 
this would raise an error:

   (plot3d (list (surface3d / -2 1 -2 1)
                 (surface3d + -1 2 -1 2)))

because the bounds are extended to [-2,2]x[-2,2] accommodate the `+` 
surface renderer, so 0 would be sampled.

----

In a sense, what I really want is impossible. With any 
exception-swallowing rule I make, someone could write a function that 
raises an exception that Plot eats when it shouldn't, or re-raises when 
it shouldn't. Someone could try plotting a function that, for some 
reason, tries to compute (gamma 0) if a `vector-ref` goes out of bounds.

But I think it could behave properly in the most common cases if it were 
possible to tell the difference between the errors raised by (gamma 0) 
and (vector-ref vs (length vs)). Right now, there's no way to do that.

Neil ⊥

On 05/21/2014 10:16 AM, Robby Findler wrote:
> I meant to suggest that plot should raise any error that a function it
> calls raises. Is there something wrong with doing that?
>
> Robby
>
> On Wed, May 21, 2014 at 11:09 AM, Neil Toronto <neil.toronto at gmail.com> wrote:
>> Referencing an identifier before its definition raises an
>> `exn:fail:contract:variable`. So that would put Plot in the weird position
>> of having to distinguish different kinds of contract errors, but not by
>> using subtypes or any other simple rule.
>>
>> Maybe we should have an `exn:fail:contract:math` or
>> `exn:fail:contract:domain` or `exn:fail:contract:argument` and make
>> `exn:fail:contract:divide-by-zero` a subtype of it. I'd gladly change Plot
>> to ignore just those, and change the math library to raise more specific
>> errors.
>>
>> (log 0) raises an `exn:fail:contract:divide-by-zero`, which is a terminology
>> stretch that suggests we need a bit of refactoring anyway.
>>
>> Neil ⊥
>>
>>
>> On 05/21/2014 09:51 AM, Robby Findler wrote:
>>>
>>> IMO, plot should raise that exception.
>>>
>>> Robby
>>>
>>> On Wed, May 21, 2014 at 10:37 AM, Laurent <laurent.orseau at gmail.com>
>>> wrote:
>>>>
>>>> ... it eats everything! (particularly exceptions)
>>>> For example, it is perfectly happy with the following:
>>>>
>>>> % racket
>>>> Welcome to Racket v6.0.1.7.
>>>>>
>>>>> (require plot)
>>>>> (plot (function (lambda(x)(+ x n)))
>>>>
>>>>     #:x-min 0 #:x-max 10 #:y-min 0 #:y-max 10)
>>>> (object:2d-plot-snip% ...)
>>>>
>>>> ... although n is clearly undefined. Presumably this is to avoid breaking
>>>> on
>>>> math errors like `(/ 0)` ?
>>>>
>>>> Would it make sense to have an `exn:fail:arithmetic` exception struct so
>>>> that `function` would only catch those?
>>>>
>>>> Laurent
>>>>
>>>>
>>>> ____________________
>>>>     Racket Users list:
>>>>     http://lists.racket-lang.org/users
>>>>
>>> ____________________
>>>     Racket Users list:
>>>     http://lists.racket-lang.org/users
>>>
>>
>> ____________________
>>   Racket Users list:
>>   http://lists.racket-lang.org/users


Posted on the users mailing list.