[racket] Plot is voracious

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

That's the kind of thing I had in mind, but I was also thinking of 
subtyping-like relations in the exception hierarchy. For example, does 
it make sense to change a contract to raise a less specific error? Does 
it matter?

At any rate, it seems we might need code to be able to catch and handle 
different contract violations different ways. Raising only one kind of 
error is fine when humans are handling them, but programs like Plot are 
too stupid to read error messages.

 From your response, it seems safe for now to insert another level in 
the exception hierarchy for math domain errors, so I'll make a bug 
report about it and assign it to myself.

Neil ⊥

On 05/21/2014 12:29 PM, Robby Findler wrote:
> Oh! Interesting thought. Right now, the contract system always raises
> the same exception.
>
> But I'm having trouble seeing what's the generalization.
>
> It would be easy to make contracts that do the same checking as
> existing contracts but that raise more specific errors, and even have
> combinators that take a "normal" contract and turn it into one that
> raises a specific exception, ie a contract that checks to see if its
> input is a number and not positive and raises one exception in that
> cases and a different exception in the case that it gets a non-number
> entirely.
>
> Is that what you have in mind?
>
> Robby
>
> On Wed, May 21, 2014 at 1:17 PM, Neil Toronto <neil.toronto at gmail.com> wrote:
>> 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.