[racket] Plot is voracious
Yes, true. We shouldn't do that. Sorry.
On Wed, May 21, 2014 at 1:02 PM, Sam Tobin-Hochstadt
<samth at cs.indiana.edu> wrote:
> Changing the default behavior like that seems like it would
> potentially break a lot of people's plots.
>
> Sam
>
> On Wed, May 21, 2014 at 1:22 PM, Robby Findler
> <robby at eecs.northwestern.edu> wrote:
>> How about adding yet another argument to plot #:errors-go-to-nan or
>> something like that, such that plot's default behavior is to let the
>> errors thru, but that, if you turn that flag on, then it just swallows
>> all errors?
>>
>> Robby
>>
>> On Wed, May 21, 2014 at 12:18 PM, Neil Toronto <neil.toronto at gmail.com> wrote:
>>> 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
>>>
>>>
>>
>> ____________________
>> Racket Users list:
>> http://lists.racket-lang.org/users