[racket] Plot is voracious

From: Neil Toronto (neil.toronto at gmail.com)
Date: Wed May 21 14:17:33 EDT 2014

I thought there might be a contract-system-y reason; e.g. if I wanted to 
change `gamma` to raise errors on exact, nonpositive integers using a 
contract. Or maybe something deeper that has to do with composing 
contracts using `or/c` and `and/c`. Nothing like that?

Neil ⊥

On 05/21/2014 12:09 PM, Robby Findler wrote:
> I don't think there is a problem with adding that exception, except
> that it seems pretty laborious. And probably someone (and I can't
> think of anyone better than you to do this, Neil!) may find that there
> are actually 2 or 3 exns that are the right set.
>
> I think that if you wanted to take this on, Racketeers everywhere
> would thank you.
>
> Robby
>
> On Wed, May 21, 2014 at 1:05 PM, Neil Toronto <neil.toronto at gmail.com> wrote:
>> Based on experience using Plot, I believe allowing all errors is a terrible
>> default.
>>
>> Jay's suggestion would make it easier to ignore only some errors, especially
>> if it were a parameter. I could see doing
>>
>>    (plot-swallow-exception? exn:fail:contract:divide-by-zero?)
>>
>> To make it as backwards-compatible as possible while being precise, it would
>> be nice if it could swallow only math domain errors by default. But again,
>> there's no way to distinguish those from other errors.
>>
>> Is there a problem with adding `exn:fail:contract:math` and making
>> `exn:fail:contract:divide-by-zero` a subtype?
>>
>> Neil ⊥
>>
>>
>> On 05/21/2014 11:25 AM, Jay McCarthy wrote:
>>>
>>> Or
>>>
>>> #:catch-these-exns-plot! [catch-exn? void]
>>>
>>> Jay
>>>
>>> On Wed, May 21, 2014 at 11:22 AM, 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
>>>
>>>
>>>
>>>
>>


Posted on the users mailing list.